├── README.md ├── avl_tree.py ├── b-tree.py ├── btree_traversal.py ├── chains.py ├── factorial.py ├── graphviz_example.py ├── heap_example.py ├── insertion.py ├── linked_list.py ├── merge.py ├── rbtree.py ├── traversal_test ├── tree_13_09.py └── tree_20.09.py /README.md: -------------------------------------------------------------------------------- 1 | # algorithms_code -------------------------------------------------------------------------------- /avl_tree.py: -------------------------------------------------------------------------------- 1 | import graphviz 2 | import sys 3 | 4 | class Node: 5 | def __init__(self, key): 6 | self.key = key 7 | self.left = None 8 | self.right = None 9 | self.height = 0 # высота считается в ребрах 10 | 11 | def __str__(self): 12 | left = self.left.key if self.left else None 13 | right = self.right.key if self.right else None 14 | return 'key: {}, left: {}, right: {}'.format(self.key, left, right) 15 | 16 | 17 | def breadth_first_search(root, dot): 18 | queue = [root] 19 | dot.node(str(root.key)) 20 | while queue: 21 | tmp_queue = [] 22 | for element in queue: 23 | if element.left: 24 | dot.node(str(element.left.key)) 25 | dot.edge(str(element.key), str(element.left.key)) 26 | tmp_queue.append(element.left) 27 | if element.right: 28 | dot.node(str(element.right.key)) 29 | dot.edge(str(element.key), str(element.right.key)) 30 | tmp_queue.append(element.right) 31 | queue = tmp_queue 32 | 33 | class AVLTree: 34 | def __init__(self): 35 | self.root = None 36 | 37 | def insert(self, key): 38 | if not self.root: 39 | self.root = Node(key) 40 | else: 41 | self.root = self.insert_rec(key, self.root) 42 | 43 | def insert_rec(self, key, node): 44 | if not node: 45 | node = Node(key) 46 | 47 | elif key < node.key: 48 | node.left = self.insert_rec(key, node.left) 49 | # после добавления левого поддерева 50 | else: 51 | node.right = self.insert_rec(key, node.right) 52 | if self.get_height(node.right) - self.get_height(node.left) == 2: 53 | if key < node.right.key: 54 | node = self.big_left_rotate(node) 55 | else: 56 | node = self.small_left_rotate(node) 57 | node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1 58 | return node 59 | 60 | def get_height(self, node): 61 | if not node: 62 | return -1 63 | else: 64 | return node.height 65 | 66 | def small_left_rotate(self, node_a): 67 | node_b = node_a.right 68 | Lb = node_b.left 69 | node_a.right = Lb 70 | node_b.left = node_a 71 | 72 | node_a.height = max(self.get_height(node_a.right), self.get_height(node_a.left)) + 1 73 | node_b.height = max(self.get_height(node_b.right), self.get_height(node_b.left)) + 1 74 | 75 | return node_b 76 | 77 | def big_left_rotate(self, node_a): 78 | pass 79 | 80 | 81 | def main(): 82 | nodes = list(map(int, input().split())) 83 | avl_tree = AVLTree() 84 | for index, node in enumerate(nodes): 85 | dot = graphviz.Digraph() 86 | avl_tree.insert(node) 87 | breadth_first_search(avl_tree.root, dot) 88 | dot.render('g{}.gv'.format(index)) 89 | 90 | 91 | main() 92 | -------------------------------------------------------------------------------- /b-tree.py: -------------------------------------------------------------------------------- 1 | import graphviz 2 | 3 | 4 | class Node: 5 | def __init__(self, leaf): 6 | self.keys = [] 7 | self.children = [] 8 | self.leaf = leaf # лист? 9 | 10 | def __str__(self): 11 | return ', '.join(map(str, self.keys)) if self.keys else 'None' 12 | 13 | 14 | def breadth_first_search(root, dot): 15 | queue = [root] 16 | dot.node(str(root), shape='box') 17 | while queue: 18 | tmp_queue = [] 19 | for element in queue: 20 | for child in element.children: 21 | dot.node(str(child), shape='box') 22 | dot.edge(str(element), str(child)) 23 | tmp_queue.append(child) 24 | queue = tmp_queue 25 | 26 | 27 | class BTree: 28 | def __init__(self, t): 29 | self.root = Node(True) 30 | self.t = t 31 | 32 | def insert(self, key): 33 | root = self.root 34 | if not len(root.keys): # пустое дерево 35 | self.root.keys.append(key) 36 | 37 | elif len(root.keys) == 2 * self.t - 1: # количество ключей максимально возможно, превентивно разбиваем узел 38 | 39 | new_node = Node(False) 40 | self.root = new_node 41 | new_node.children.append(root) 42 | self.split_child(new_node, 0) 43 | self.insert_non_full(new_node, key) 44 | 45 | else: 46 | self.insert_non_full(root, key) 47 | 48 | def split_child(self, node, index): # node - узел, ребенка которого будут делить, index - куда отправится узел посередине 49 | left_half = node.children[index] 50 | right_half = Node(left_half.leaf) 51 | 52 | node.keys.insert(index, left_half.keys[self.t-1]) # добавляем узел посередине 53 | 54 | right_half.keys = left_half.keys[self.t:] 55 | left_half.keys = left_half.keys[:self.t-1] 56 | 57 | if not left_half.leaf: 58 | right_half.children = left_half.children[self.t:] 59 | left_half.children = left_half.children[:self.t] 60 | 61 | node.children.insert(index+1, right_half) # сразу после i-го (левого) ребенка 62 | 63 | 64 | def insert_non_full(self, node, key): # элемент всегда добавляется в лист 65 | i = len(node.keys) - 1 66 | 67 | if node.leaf: 68 | 69 | while i >= 0 and key < node.keys[i]: # поиск места для вставки элемента 70 | i -= 1 71 | node.keys.insert(i+1, key) 72 | 73 | else: 74 | while i >= 0 and key < node.keys[i]: # поиск индекса нужного ребенка 75 | i -= 1 76 | i += 1 77 | 78 | if len(node.children[i].keys) == 2 * self.t - 1: # количество ключей максимально возможно, превентивно разбиваем узел 79 | 80 | self.split_child(node, i) 81 | 82 | if key > node.keys[i]: # идем ли мы в правую часть детей после сплита 83 | i += 1 84 | self.insert_non_full(node.children[i], key) 85 | 86 | 87 | def main(): 88 | nodes = list(map(int, input().split())) 89 | b_tree = BTree(3) 90 | for index, node in enumerate(nodes): 91 | dot = graphviz.Digraph() 92 | b_tree.insert(node) 93 | breadth_first_search(b_tree.root, dot) 94 | dot.render('g{}.gv'.format(chr(index + 65))) 95 | 96 | 97 | main() 98 | -------------------------------------------------------------------------------- /btree_traversal.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Node: 4 | def __init__(self, key): 5 | self.key = key 6 | self.left = None 7 | self.right = None 8 | 9 | def __str__(self): 10 | left = self.left.key if self.left else None 11 | right = self.right.key if self.right else None 12 | return 'key: {}, left: {}, right: {}'.format(self.key, left, right) 13 | 14 | 15 | def read_data(): 16 | n = int(input()) 17 | nodes = [Node(0) for _ in range(n)] 18 | for i in range(n): 19 | key, left, right = map(int, sys.stdin.readline().split()) 20 | nodes[i].key = key 21 | if left != -1: 22 | nodes[i].left = nodes[left] 23 | if right != -1: 24 | nodes[i].right = nodes[right] 25 | return nodes[0] 26 | 27 | 28 | def in_order(current, result): 29 | if not current: 30 | return 31 | in_order(current.left, result) 32 | result.append(current.key) 33 | in_order(current.right, result) 34 | return result 35 | 36 | 37 | def pre_order(current): 38 | if not current: 39 | return 40 | print(current.key, end=' ') 41 | pre_order(current.left) 42 | pre_order(current.right) 43 | 44 | 45 | def breadth_first_search(root): 46 | queue = [root] 47 | while queue: 48 | tmp_queue = [] 49 | for element in queue: 50 | print(element.key, end=' ') 51 | if element.left: 52 | tmp_queue.append(element.left) 53 | if element.right: 54 | tmp_queue.append(element.right) 55 | queue = tmp_queue 56 | print() 57 | 58 | 59 | def main(): 60 | root = read_data() 61 | print(in_order(root, [])) 62 | pre_order(root) 63 | print() 64 | print('-'*80) 65 | breadth_first_search(root) 66 | 67 | 68 | main() 69 | -------------------------------------------------------------------------------- /chains.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data, next_element=None): 3 | self.data = data 4 | self.next_element = next_element 5 | 6 | 7 | def hashing(string, m): 8 | p = 1000000007 9 | x = 263 10 | tmp_sum = sum([(ord(element) * x ** k) % p for k, element in enumerate(string)]) 11 | return tmp_sum % p % m 12 | 13 | 14 | def add(string, ht, m): 15 | h = hashing(string, m) 16 | cell = ht[h] 17 | node = Node(string) 18 | if not cell: 19 | ht[h] = node 20 | else: 21 | node.next_element = cell 22 | ht[h] = node 23 | 24 | 25 | def find(string, ht, m): 26 | result = 'no' 27 | h = hashing(string, m) 28 | cell = ht[h] 29 | if not cell: 30 | return result 31 | while cell: 32 | if cell.data == string: 33 | result = 'yes' 34 | return result 35 | cell = cell.next_element 36 | return result 37 | 38 | 39 | def main(): 40 | m = int(input()) 41 | ht = [None for _ in range(m)] 42 | n = int(input()) 43 | for i in range(n): 44 | command, arg = input().split() 45 | if command == 'add': 46 | add(arg, ht, m) 47 | elif command == 'find': 48 | find(arg, ht, m) 49 | else: 50 | print('bad command') 51 | 52 | 53 | main() 54 | -------------------------------------------------------------------------------- /factorial.py: -------------------------------------------------------------------------------- 1 | def f_iter(n): 2 | res = 1 3 | while n > 1: 4 | res *= n 5 | n -= 1 6 | return res 7 | 8 | def f_rec(n): 9 | if n == 1: 10 | return 1 11 | res = n * f_rec(n-1) 12 | return res 13 | 14 | #f_rec(1000) 15 | print(f_iter(2), f_iter(4)) 16 | print(f_rec(2), f_rec(4)) 17 | -------------------------------------------------------------------------------- /graphviz_example.py: -------------------------------------------------------------------------------- 1 | import graphviz 2 | import sys 3 | 4 | class Node: 5 | def __init__(self, key): 6 | self.key = key 7 | self.left = None 8 | self.right = None 9 | 10 | def __str__(self): 11 | left = self.left.key if self.left else None 12 | right = self.right.key if self.right else None 13 | return 'key: {}, left: {}, right: {}'.format(self.key, left, right) 14 | 15 | 16 | def read_data(): 17 | n = int(input()) 18 | nodes = [Node(0) for _ in range(n)] 19 | for i in range(n): 20 | key, left, right = map(int, sys.stdin.readline().split()) 21 | nodes[i].key = key 22 | if left != -1: 23 | nodes[i].left = nodes[left] 24 | if right != -1: 25 | nodes[i].right = nodes[right] 26 | return nodes[0] 27 | 28 | 29 | def breadth_first_search(root, dot): 30 | queue = [root] 31 | dot.node(str(root.key)) 32 | while queue: 33 | tmp_queue = [] 34 | for element in queue: 35 | if element.left: 36 | dot.node(str(element.left.key)) 37 | dot.edge(str(element.key), str(element.left.key)) 38 | tmp_queue.append(element.left) 39 | if element.right: 40 | dot.node(str(element.right.key)) 41 | dot.edge(str(element.key), str(element.right.key)) 42 | tmp_queue.append(element.right) 43 | queue = tmp_queue 44 | 45 | 46 | 47 | def main(): 48 | root = read_data() 49 | dot = graphviz.Digraph() 50 | breadth_first_search(root, dot) 51 | dot.render('g1.gv') 52 | 53 | 54 | main() 55 | 56 | -------------------------------------------------------------------------------- /heap_example.py: -------------------------------------------------------------------------------- 1 | class Heap: 2 | def __init__(self): 3 | self.MAX_SIZE = 20 4 | self.heap = [None] * self.MAX_SIZE 5 | self.size = 0 6 | 7 | @staticmethod 8 | def get_parent(index): 9 | return (index - 1) // 2 10 | 11 | @staticmethod 12 | def get_left_child(index): 13 | return 2 * index + 1 14 | 15 | @staticmethod 16 | def get_right_child(index): 17 | return 2 * index + 2 18 | 19 | def insert(self, element): 20 | if self.size == self.MAX_SIZE: 21 | return -1 22 | self.heap[self.size] = element 23 | self.sift_up(self.size) 24 | self.size += 1 25 | 26 | def extract_max(self): 27 | max_element = self.heap[0] 28 | self.heap[0], self.heap[self.size-1] = self.heap[self.size-1], None 29 | self.size -= 1 30 | self.sift_down(0) 31 | return max_element 32 | 33 | def sift_up(self, index): 34 | parent = self.get_parent(index) 35 | while index > 0 and self.heap[parent] < self.heap[index]: 36 | self.heap[parent], self.heap[index] = self.heap[index], self.heap[parent] 37 | index = parent 38 | parent = self.get_parent(index) 39 | 40 | def sift_down(self, index): 41 | left = self.get_left_child(index) 42 | right = self.get_right_child(index) 43 | if left >= self.size and right >= self.size: 44 | return 45 | if right >= self.size: 46 | max_index = left if self.heap[left] > self.heap[index] else index 47 | else: 48 | max_index = left if self.heap[left] > self.heap[right] else right 49 | max_index = max_index if self.heap[max_index] > self.heap[index] else index 50 | if max_index != index: 51 | self.heap[max_index], self.heap[index] = self.heap[index], self.heap[max_index] 52 | self.sift_down(max_index) 53 | 54 | def __str__(self): 55 | return str(self.heap) 56 | 57 | 58 | def main(): 59 | heap = Heap() 60 | heap.insert(5) 61 | heap.insert(7) 62 | heap.insert(3) 63 | heap.insert(6) 64 | heap.insert(8) 65 | print(heap) 66 | heap.extract_max() 67 | print(heap) 68 | heap.extract_max() 69 | print(heap) 70 | 71 | 72 | main() 73 | -------------------------------------------------------------------------------- /insertion.py: -------------------------------------------------------------------------------- 1 | def insert(arr): 2 | for index in range(1, len(arr)): 3 | current = arr[index] 4 | sorted_index = index-1 5 | while sorted_index >= 0 and current < arr[sorted_index]: 6 | arr[sorted_index+1] = arr[sorted_index] 7 | sorted_index -= 1 8 | arr[sorted_index+1] = current 9 | return arr 10 | 11 | 12 | arr = list(map(int, input().split())) 13 | print(insert(arr)) 14 | -------------------------------------------------------------------------------- /linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data, next_element=None): 3 | self.data = data 4 | self.next_element = next_element 5 | 6 | def __str__(self): 7 | next_element = None 8 | if self.next_element: 9 | next_element = self.next_element.data 10 | return 'data: {}, next_element: {}\n'.format(self.data, next_element) 11 | 12 | class LinkedList: 13 | def __init__(self, root, tail): 14 | self.root = root 15 | self.tail = tail 16 | self.root.next_element = tail 17 | self.length = 2 18 | 19 | def __len__(self): 20 | return self.length 21 | 22 | def find(self, data): 23 | current = self.root 24 | while current: 25 | if current.data == data: 26 | return current 27 | current = current.next_element 28 | return 'not found\n' 29 | 30 | def append(self, root_element, element): 31 | if root_element.next_element: 32 | next_element = root_element.next_element 33 | root_element.next_element = element 34 | element.next_element = next_element 35 | else: 36 | root_element.next_element = element 37 | self.tail = element 38 | self.length += 1 39 | 40 | 41 | root = Node('A') 42 | tail = Node('z') 43 | linked_list = LinkedList(root, tail) 44 | print(linked_list.root, linked_list.tail) 45 | print(len(linked_list)) 46 | print('-'*80) 47 | new_node = Node('t') 48 | linked_list.append(root, new_node) 49 | new_node = Node('Q') 50 | linked_list.append(tail, new_node) 51 | print('try to find t:', linked_list.find('t'), 'try to find Q:', linked_list.find('Q')) 52 | print(len(linked_list)) 53 | -------------------------------------------------------------------------------- /merge.py: -------------------------------------------------------------------------------- 1 | def merge(arr): # 4 3 2 1 2 | if len(arr) == 1: 3 | return 4 | middle = len(arr) // 2 5 | left, right = arr[:middle], arr[middle:] 6 | merge(left) 7 | merge(right) 8 | index_left = index_right = index = 0 9 | result = [0] * (len(left) + len(right)) 10 | while index_left < len(left) and index_right < len(right): 11 | if left[index_left] <= right[index_right]: 12 | result[index] = left[index_left] 13 | index_left += 1 14 | else: 15 | result[index] = right[index_right] 16 | index_right += 1 17 | index += 1 18 | while index_left < len(left): 19 | result[index] = left[index_left] 20 | index_left += 1 21 | index += 1 22 | while index_right < len(right): 23 | result[index] = right[index_right] 24 | index_right += 1 25 | index += 1 26 | for i in range(len(arr)): 27 | arr[i] = result[i] 28 | return arr 29 | 30 | 31 | 32 | 33 | arr = list(map(int, input().split())) 34 | print(merge(arr)) 35 | -------------------------------------------------------------------------------- /rbtree.py: -------------------------------------------------------------------------------- 1 | import graphviz 2 | 3 | BLACK = 'black' 4 | RED = 'red' 5 | 6 | 7 | class Node: 8 | def __init__(self, key, color, parent=None): 9 | self.key = key 10 | self.left = None 11 | self.right = None 12 | self.color = color 13 | self.parent = parent 14 | 15 | def __str__(self): 16 | left = self.left.key if self.left else None 17 | right = self.right.key if self.right else None 18 | parent = self.parent.key if self.parent else None 19 | return 'key: {}, left: {}, right: {}, color: {}, parent: {}'.format(self.key, left, right, self.color, parent) 20 | 21 | 22 | def breadth_first_search(root, dot): 23 | queue = [root] 24 | dot.node(str(root.key), color=root.color) 25 | while queue: 26 | tmp_queue = [] 27 | for element in queue: 28 | if element.left: 29 | dot.node(str(element.left.key), color=element.left.color) 30 | dot.edge(str(element.key), str(element.left.key)) 31 | tmp_queue.append(element.left) 32 | if element.right: 33 | dot.node(str(element.right.key), color=element.right.color) 34 | dot.edge(str(element.key), str(element.right.key)) 35 | tmp_queue.append(element.right) 36 | queue = tmp_queue 37 | 38 | 39 | class RBTree: 40 | def __init__(self): 41 | self.root = None 42 | 43 | def insert(self, key): 44 | if not self.root: 45 | self.root = Node(key, BLACK) 46 | else: 47 | current = self.root 48 | while current: 49 | if key < current.key: 50 | if not current.left: 51 | new_node = Node(key, RED, parent=current) 52 | current.left = new_node 53 | break 54 | current = current.left 55 | else: 56 | if not current.right: 57 | new_node = Node(key, RED, parent=current) 58 | current.right = new_node 59 | break 60 | current = current.right 61 | self.fix_tree(new_node) 62 | 63 | def fix_tree(self, node): 64 | while node.parent and node.parent.color == RED: 65 | grandparent = node.parent.parent 66 | if node.parent == grandparent.left: 67 | uncle = grandparent.right 68 | 69 | if not uncle or uncle.color == BLACK: # дядя отсутствует или черный 70 | if node == node.parent.right: 71 | node = node.parent 72 | self.left_rotate(node) 73 | self.right_rotate(grandparent) 74 | node.parent.color = BLACK 75 | grandparent.color = RED 76 | 77 | else: # дядя красный 78 | uncle.color = BLACK 79 | node.parent.color = BLACK 80 | grandparent.color = RED 81 | node = grandparent 82 | else: # если родитель нового узла правый сын 83 | pass 84 | if self.root.color == RED: 85 | self.root.color = BLACK 86 | 87 | def left_rotate(self, node): # node - отец нового элемента 88 | new_node = node.right 89 | parent = node.parent 90 | 91 | node.right = new_node.left # Lb 92 | if node.right: 93 | node.right.parent = node 94 | 95 | new_node.left = node 96 | node.parent = new_node 97 | 98 | if not parent: 99 | self.root = new_node 100 | 101 | else: 102 | if parent.left == node: 103 | parent.left = new_node 104 | else: 105 | parent.right = new_node 106 | 107 | def right_rotate(self, node): 108 | new_node = node.left 109 | parent = node.parent 110 | 111 | node.left = new_node.right 112 | if node.left: 113 | node.left.parent = node 114 | 115 | new_node.right = node 116 | node.parent = new_node 117 | 118 | if not parent: 119 | self.root = new_node 120 | 121 | else: 122 | if parent.left == node: 123 | parent.left = new_node 124 | else: 125 | parent.right = new_node 126 | 127 | 128 | def main(): 129 | nodes = list(map(int, input().split())) 130 | rb_tree = RBTree() 131 | for index, node in enumerate(nodes): 132 | dot = graphviz.Digraph() 133 | rb_tree.insert(node) 134 | breadth_first_search(rb_tree.root, dot) 135 | dot.render('g{}.gv'.format(index)) 136 | 137 | 138 | main() 139 | -------------------------------------------------------------------------------- /traversal_test: -------------------------------------------------------------------------------- 1 | 6 2 | 10 1 2 3 | 7 3 4 4 | 5 -1 5 5 | 2 -1 -1 6 | 6 -1 -1 7 | 4 -1 -1 8 | -------------------------------------------------------------------------------- /tree_13_09.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.elements = [] 5 | 6 | def __str__(self): 7 | next_elements = [] 8 | if self.elements: 9 | for element in self.elements: 10 | next_elements.append(element.data) 11 | return 'data: {}, next_element: {}\n'.format(self.data, next_elements) 12 | 13 | def append_children(self, children): 14 | self.elements.extend(children) 15 | 16 | 17 | class Tree: 18 | def __init__(self, root): 19 | self.root = root 20 | 21 | def print_tree(self, element): 22 | print(element) 23 | for child in element.elements: 24 | self.print_tree(child) 25 | 26 | 27 | root = Node('A') 28 | arr_nodes = [Node(chr(i)) for i in range(66, 70)] 29 | root.append_children(arr_nodes) 30 | 31 | arr_nodes_1 = [Node(chr(i)) for i in range(70, 72)] 32 | arr_nodes[1].append_children(arr_nodes_1) 33 | 34 | tree = Tree(root) 35 | tree.print_tree(root) 36 | -------------------------------------------------------------------------------- /tree_20.09.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.elements = [] 5 | 6 | def __str__(self): 7 | next_elements = [] 8 | if self.elements: 9 | for element in self.elements: 10 | next_elements.append(element.data) 11 | return 'data: {}, next_element: {}\n'.format(self.data, next_elements) 12 | 13 | def append_children(self, children): 14 | self.elements.extend(children) 15 | 16 | 17 | class Tree: 18 | def __init__(self, root): 19 | self.root = root 20 | 21 | def print_tree(self, element): 22 | print(element) 23 | for child in element.elements: 24 | self.print_tree(child) 25 | return 26 | 27 | def height(self, current_root): 28 | result_height = 1 29 | for child in current_root.elements: 30 | result_height = max(result_height, 1+self.height(child)) 31 | return result_height 32 | 33 | 34 | root = Node('A') 35 | arr_nodes = [Node(chr(i)) for i in range(66, 70)] 36 | root.append_children(arr_nodes) 37 | 38 | arr_nodes_1 = [Node(chr(i)) for i in range(70, 72)] 39 | arr_nodes[1].append_children(arr_nodes_1) 40 | 41 | arr_nodes_2 = [Node(chr(i)) for i in range(72, 74)] 42 | arr_nodes_1[0].append_children(arr_nodes_2) 43 | tree = Tree(root) 44 | tree.print_tree(root) 45 | print(tree.height(root)) 46 | --------------------------------------------------------------------------------