Skip to content

Commit 51dfedc

Browse files
committed
readme done
1 parent 34ea4f2 commit 51dfedc

File tree

8 files changed

+466
-48
lines changed

8 files changed

+466
-48
lines changed

README.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
# [Technopark](https://park.vk.company/) algorithms
22
Реализация различных алгоритмов на С / С++ для первого семестра Технопарка.
33

4-
* [Алгоритм Дейкстры для разреженных графов.](
5-
https://github.com/OlegSchwann/Technopark-algorithms/blob/master/3-й%20модуль/3%20задание/main.cpp)
6-
* [Вычисление всех возможных кратчайших путей в неорентированном графе.](
7-
https://github.com/OlegSchwann/Technopark-algorithms/blob/master/3-й%20модуль/2%20задание/main.cpp)
8-
* [4 разных реализации хранения графов.](
9-
https://github.com/OlegSchwann/Technopark-algorithms/tree/master/3-й%20модуль/1%20задание)
10-
* [Самобалансирующееся АВЛ-дерево.](
11-
https://github.com/OlegSchwann/Technopark-algorithms/blob/master/2-й%20модуль/4%20задание%201%20вариант/main.cpp)
12-
* [Декартово дерево.](
13-
https://github.com/OlegSchwann/Technopark-algorithms/blob/master/2-й%20модуль/3%20задание%201%20вариант/main.cpp)
4+
# Модуль 3
5+
* [Алгоритм Дейкстры для разреженных графов(задача поиска кратчайшего расстояния между городами).](modules3/cities/main.cpp)
6+
* [Вычисление всех возможных кратчайших путей в неорентированном графе.](module3/NumbOfShortestPaths/main.cpp)
7+
* [4 разных реализации хранения графов(условие задания):](modeule3/Graphs/README(условие).md)
8+
- [ListGraph](ListGraph/src/ListGraph.cpp), хранящий граф в виде массива списков смежности,
9+
- [MatrixGraph](MatrixGraph/src/MatrixGraph.cpp), хранящий граф в виде матрицы смежности,
10+
- [SetGraph](SetGraph/src/SetGraph.cpp), хранящий граф в виде массива хэш-таблиц/сбалансированных деревьев поиска,
11+
- [ArcGraph](ArcGraph/src/ArcGraph.cpp), хранящий граф в виде одного массива пар {from, to}.
12+
### Модуль 2
13+
* [Самобалансирующееся АВЛ-дерево. Реализация + решение задачи про распределению солдат по росту](module2/AVL_tree_using(soilders)/main.cpp)
14+
* [Декартово дерево.](module2/сartesian_tree/main.cpp)
1415
* [Обход бинарного дерева поиска в порядке in-order без рекурсии.](module2/binary-tree/main.cpp)
1516
* [Хеш-таблица с открытой адресацией и разрешением коллизий методом квадратичного пробирования. Вычисление хеша методом Горнера.](module2/hash_table/main.cpp)
1617
### Модуль 1
17-
* [Реализация сортировки слиянием. Решение задачи на кол-во показов рекламы клиенту.](module1/7/adv_cpint_merge_sort.cpp)
18+
* [Реализация сортировки слиянием. Решение задачи на кол-во показов рекламы клиенту.](module1/7/adv_count_merge_sort.cpp)
1819
* [Алгоритм поиска k-й порядковой статистики (числа которое бы стояло на позиции с индексом k в отсортированном массиве). Поиск медианы и перцентили.](module1/6/main.cpp)
1920
* [Слиянеие K отсортированных массивов при помощи кучи.(Heap merge)](module1/4/heap_merge.cpp)
2021
* [Реализация очереди на двух стеках.](module1/3.3/queue.cpp)
2122
* [Реализация дека на зацикленном динамическом буффере.](module1/3/deq2.cpp)
2223
* [Нахождение пересечения двух массивов неповторяющихся целых чисел, упорядоченных по возрастанию.](module1/2.3/binary3.cpp)
2324
* [Бинарный и экспоненциальный поиск. Найти границу после которой массив строго убывает за log(m).](module1/2/binary.cpp)
24-
* [Работа с битовм сдвигом. Проверка по маске](module1/1/bit.cpp)
25+
* [Работа с битовым сдвигом. Проверка по маске](module1/1/bit.cpp)

module2/AVL_tree_using(soilders)/main.cpp

Lines changed: 121 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,54 @@
1616
//На каждую команду 1 (добавление в строй) вы должны выводить число K – номер позиции, на которую должен встать этот
1717
//солдат (все стоящие за ним двигаются назад).
1818

19+
/*
20+
Пример 1
21+
Ввод
22+
5
23+
1 100
24+
1 200
25+
1 50
26+
2 1
27+
1 150
28+
Вывод
29+
0
30+
0
31+
2
32+
1
33+
Пример 2
34+
Ввод
35+
36+
15
37+
1 41
38+
1 18467
39+
2 0
40+
1 26500
41+
1 19169
42+
2 1
43+
1 11478
44+
1 29358
45+
2 2
46+
1 24464
47+
1 5705
48+
2 0
49+
1 23281
50+
1 16827
51+
2 1
52+
Вывод
53+
0
54+
0
55+
0
56+
1
57+
1
58+
0
59+
2
60+
3
61+
2
62+
3
63+
*/
64+
65+
66+
1967
#include <iostream>
2068

2169
template<class T>
@@ -95,6 +143,20 @@ class AVLTree {
95143

96144
}
97145

146+
/* Вставка ключей
147+
Вставка нового ключа в АВЛ-дерево выполняется, так же, как это делается в простых деревьях поиска:
148+
спускаемся вниз по дереву, выбирая правое или левое направление движения
149+
в зависимости от результата сравнения ключа в текущем узле и вставляемого ключа.
150+
Единственное отличие заключается в том, что при возвращении из рекурсии
151+
(после того, как ключ вставлен либо в правое, либо в левое поддерево, и это дерево сбалансировано)
152+
выполняется балансировка текущего узла. Строго доказывается, что возникающий при такой вставке дисбаланс
153+
в любом узле по пути движения не превышает двух,
154+
а значит применение вышеописанной функции балансировки является корректным.
155+
Важно, что балансировка дерева не нарушает позицию в массиве (порядковую статистику каждого элемента)
156+
Можно считать новый индекс и до того, как мы окончательно добавили новый узел.
157+
если идём налево при выборе ничего не прибавляем
158+
если идём направо - прибавляем количество элементов слева + 1
159+
*/
98160
Node *insertInternal(const Key &key, Node *node, size_t &position) {
99161
if (!node) {
100162
return new Node(key);
@@ -108,7 +170,18 @@ class AVLTree {
108170
}
109171
return balance(node);
110172
}
111-
173+
174+
/* Удаление ключей
175+
С удалением узлов из АВЛ-дерева, все не так просто, как с рандомизированными деревьями поиска.
176+
Идея следующая: находим узел x с заданным ключом k (если не находим, то делать ничего не надо),
177+
в правом поддереве находим узел min с наименьшим ключом и заменяем удаляемый узел p на найденный узел min.
178+
Если у найденного узела x нет правого поддерева, то по свойству АВЛ-дерева слева у этого узла может
179+
быть только один единственный дочерний узел (дерево высоты 1), либо узел p вообще лист.
180+
В обоих этих случаях надо просто удалить узел p и вернуть в качестве результата
181+
указатель на левый дочерний узел узла x.
182+
Пусть теперь правое поддерево у x есть. Находим минимальный ключ в этом поддереве.
183+
По свойству двоичного дерева поиска этот ключ находится в конце левой ветки, начиная от корня дерева.
184+
Применяем рекурсивную функцию: */
112185
Node *eraseInternal(size_t position, Node *node) {
113186
if (!node || position > get_num_of_el(node)) {
114187
return nullptr;
@@ -137,7 +210,12 @@ class AVLTree {
137210
}
138211
return balance(node);
139212
}
140-
213+
/*Очевидно, что операции вставки и удаления (а также более простая операция поиска)
214+
выполняются за время пропорциональное высоте дерева, т.к. в процессе выполнения этих операций производится
215+
спуск из корня к заданному узлу, и на каждом уровне выполняется некоторое фиксированное число действий. А в
216+
силу того, что АВЛ-дерево является сбалансированным, его высота зависит логарифмически от числа узлов. Таким
217+
образом, время выполнения всех трех базовых операций гарантированно логарифмически зависит от числа узлов дерева.*/
218+
141219
void destrInternal(Node* node){
142220
if(node){
143221
destrInternal(node->left);
@@ -162,6 +240,44 @@ class AVLTree {
162240
return balance(node);
163241
}
164242

243+
/*
244+
Балансировка узлов
245+
В процессе добавления или удаления узлов в АВЛ-дереве возможно возникновение ситуации,
246+
когда balance factor некоторых узлов оказывается равными 2 или -2, возникает расбалансировка поддерева.
247+
Для выправления ситуации применяются повороты вокруг тех или иных узлов дерева.
248+
Простой поворот вправо (влево) производит следующую трансформацию дерева:
249+
y <--левый-правый--> x
250+
/ \ / \
251+
/ \ / \
252+
x c a y
253+
/ \ /=\ /=\ / \
254+
/ \ / \
255+
a b b c
256+
/=\ /=\ /=\ /=\
257+
A < x < B < y < c
258+
Код, реализующий правый поворот, выглядит следующим образом (как обычно, каждая функция, изменяющая дерево,
259+
возвращает новый корень полученного дерева): */
260+
261+
Node *rotate_right(Node *node) {
262+
Node *tmp = node->left;
263+
node->left = tmp->right;
264+
tmp->right = node;
265+
fix_height_and_num_of_el(node);
266+
fix_height_and_num_of_el(tmp);
267+
return tmp;
268+
}
269+
270+
/* Левый поворот является симметричной копией правого: */
271+
Node *rotate_left(Node *node) {
272+
Node *tmp = node->right;
273+
node->right = tmp->left;
274+
tmp->left = node;
275+
fix_height_and_num_of_el(node);
276+
fix_height_and_num_of_el(tmp);
277+
return tmp;
278+
}
279+
280+
// Код, выполняющий балансировку, сводится к проверке условий и выполнению поворотов:
165281
Node *balance(Node *node) {
166282
fix_height_and_num_of_el(node);
167283

@@ -182,25 +298,10 @@ class AVLTree {
182298
return node;
183299
}
184300
}
301+
/* Описанные функции поворотов и балансировки также не содержат ни циклов, ни рекурсии,
302+
а значит выполняются за постоянное время, не зависящее от размера АВЛ-дерева. */
185303

186-
Node *rotate_left(Node *node) {
187-
Node *tmp = node->right;
188-
node->right = tmp->left;
189-
tmp->left = node;
190-
fix_height_and_num_of_el(node);
191-
fix_height_and_num_of_el(tmp);
192-
return tmp;
193-
}
194-
195-
Node *rotate_right(Node *node) {
196-
Node *tmp = node->left;
197-
node->left = tmp->right;
198-
tmp->right = node;
199-
fix_height_and_num_of_el(node);
200-
fix_height_and_num_of_el(tmp);
201-
return tmp;
202-
}
203-
304+
204305
int8_t get_height(Node *node) {
205306
if (node) {
206307
return node->height;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cmake_minimum_required(VERSION 3.21)
2+
project(сartesian_tree)
3+
4+
set(CMAKE_CXX_STANDARD 14)
5+
6+
add_executable(сartesian_tree main.cpp)

0 commit comments

Comments
 (0)