├── 00.Структуры_данных.md ├── LICENSE ├── README.md ├── README.ru.md └── art ├── AVLtreef.svg.png ├── Red-black_tree_example_with_NIL.svg.png ├── binom_ex_1.jpg └── logo.png /00.Структуры_данных.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Разница между массивом и связным списком 4 | 5 | Разница между массивом и связным списком заключается в том, что массив представляет собой статическую структуру 6 | данных, а связный список является динамической структурой данных. 7 | 8 | Массив и связный список - это две основные структуры данных, используемые для хранения и управления набором объектов. 9 | Они имеют следующие отличия: 10 | 11 | Память: Массив в основном занимает непрерывный блок памяти, где каждый элемент имеет свой индекс. Связный список 12 | использует "узлы", каждый из которых содержит указатель на следующий элемент списка и данные этого элемента. Это 13 | означает, что элементы списка могут располагаться в любой части памяти, а они связаны только указателями. 14 | 15 | Размер: Размер массива фиксирован, и его нельзя изменить после выделения памяти. В связном списке размер может быть 16 | изменен в любое время, добавлением или удалением элементов из списка. 17 | 18 | Вставка и удаление: В массиве процесс вставки или удаления элемента может быть затруднен, если это приведет к 19 | перераспределению памяти. В связном списке элементы могут быть вставлены или удалены просто путем изменения 20 | указателей. 21 | 22 | Удаление памяти: В массиве освобождение памяти может быть выполнено только после удаления всего массива. В связном 23 | списке память может быть удалена по мере удаления элементов, которые указывают на нее. 24 | 25 | Поиск элементов: В массиве поиск элемента является быстрее, так как элементы находятся в непрерывном блоке. В 26 | связном списке поиск может быть затруднен, так как элементы распределены в разных участках памяти, и требуется 27 | последовательная перестановка, начиная с начала списка. 28 | 29 | Таким образом, в зависимости от задачи, которую необходимо решить, выбирают подходящую структуру данных, либо массив, 30 | либо связный список. 31 | 32 | 33 | ### Применение различных структур данных python в различных алгоритмах 34 | 35 | Структура данных – это способ организации и хранения данных в программе. Они являются важной частью 36 | программирования и позволяют создавать более эффективные алгоритмы и улучшать быстродействие программы. 37 | Рассмотрим несколько примеров применения различных структур данных в алгоритмах: 38 | 39 | Структуры данных в Python - это способы организации и хранения данных в программе. В Python доступны следующие 40 | структуры данных: 41 | 42 | Списки (Lists) - это упорядоченный набор элементов. Списки можно изменять и использовать для хранения любых типов данных. 43 | 44 | Кортежи (Tuples) - это упорядоченный набор элементов, но в отличие от списков они не могут быть изменены после создания. 45 | 46 | Множества (Sets) - это коллекция уникальных элементов. Элементы множества должны быть хешируемыми. 47 | 48 | Словари (Dictionaries) - это набор пар ключ-значение. Ключи должны быть уникальными и хешируемыми. 49 | 50 | В Python также доступны специализированные структуры данных, такие как очереди, стеки и древовидные структуры. Чтобы 51 | использовать эти структуры данных, вы можете использовать библиотеки, такие как collections или heapq. 52 | 53 | 54 | #### Списки: 55 | Списки являются одной из самых используемых структур данных в Python. Они представляют собой упорядоченный 56 | набор элементов, которые могут быть изменены. Списки могут использоваться для хранения различных типов данных, 57 | включая числа, строки и другие списки. Например, в алгоритмах поиска и сортировки списки используются для хранения 58 | значений и их последующей обработки. 59 | 60 | Список (List) - это структура данных, которая позволяет хранить последовательность элементов. Основное применение 61 | списков - организация и хранение информации, упорядочивание и изменение элементов. 62 | Пример использования списка в алгоритме: сортировка пузырьком. В данном случае, мы можем использовать список для 63 | хранения неупорядоченного набора элементов, а затем, поочередно сравнивать каждый элемент с последующим и менять их 64 | местами, если это необходимо. 65 | 66 | Python использует динамическое управление памятью, что означает, что память присваивается и освобождается 67 | автоматически во время выполнения программы. 68 | 69 | В Python списки могут быть изменяемыми объектами, и поэтому память, выделенная под список, может увеличиваться и 70 | уменьшаться в зависимости от того, как его изменяют. 71 | 72 | Когда вы создаете список, Python выделяет память под каждый элемент списка. Если вам нужно создать большой список, 73 | вы можете снизить использование памяти, используя генераторы списков вместо циклов. 74 | 75 | Кроме того, если вы хотите избежать необходимости создания копии списка, вы можете использовать срезы ([start:end]), 76 | чтобы получить подмножество списка. 77 | 78 | Некоторые полезные советы для уменьшения использования памяти при работе со списками в Python: 79 | 80 | - Используйте генераторы списков вместо циклов, чтобы создавать списки 81 | - Используйте срезы ([start:end]) вместо копирования списков 82 | - Если вы работаете с большими объемами данных, можете использовать сторонние библиотеки, такие как NumPy или Pandas, 83 | которые оптимизированы для работы с массивами данных. 84 | - Если вы должны добавить много элементов в список, используйте метод extend вместо append. Метод append может 85 | привести к созданию большого количества временных списков, что потребует дополнительного использования памяти. 86 | 87 | Независимо от того, как вы используете списки, помните, что Python автоматически управляет памятью, поэтому вы 88 | можете не беспокоиться о том, что язык повредит системе из-за использования большого количества памяти. Однако 89 | оптимизация использования памяти может помочь повысить производительность вашей программы, особенно если вы 90 | работаете с большими объемами данных. 91 | 92 | Пример алгоритма python с использованием списка: 93 | ```python 94 | def find_min_element(nums): 95 | """ 96 | Функция находит наименьший элемент в списке nums и возвращает его 97 | """ 98 | min_element = nums[0] # присваиваем первый элемент в списке минимальному элементу 99 | for num in nums: # для каждого числа в списке 100 | if num < min_element: # если число меньше минимального элемента 101 | min_element = num # присваиваем минимальному элементу число 102 | return min_element # возвращаем найденный минимальный элемент 103 | 104 | my_list = [5, 8, 3, 2, 9, 1] 105 | print(find_min_element(my_list)) # вывод: 1 106 | ``` 107 | 108 | #### Словари: 109 | Словари – это структура данных, которая представляет собой неупорядоченный набор пар «ключ-значение». Они 110 | используются для быстрого доступа к данным с помощью ключа. В алгоритмах, связанных с обработкой больших объемов 111 | данных, словари могут быть использованы для хранения и обработки данных. 112 | 113 | Каждый раз, когда вы добавляете новый элемент в словарь, вы резервируете часть памяти для хранения этого элемента. 114 | Также вы можете использовать memory_profiler для измерения использования памяти при работе с вашим словарем. 115 | 116 | Ниже приведены некоторые рекомендации, которые могут помочь вам сэкономить память при работе со словарем. 117 | 118 | - Используйте defaultdict, когда это уместно. defaultdict - это подкласс словаря Python, который позволяет задавать 119 | значение по умолчанию для ключей, которые еще не существуют в словаре. Если вы используете обычный словарь Python и 120 | пытаетесь получить значение для ключа, которого нет в словаре, вы получите KeyError. 121 | - Если ваш словарь использует целочисленные ключи, и номера ключей имеют последовательный порядок, вы можете 122 | использовать список вместо словаря. 123 | - Если ваш словарь содержит множество ключей, которые являются строками, вы можете использовать OrderedDict. 124 | - Если вы работаете с большими объемами данных, вы можете использовать модуль shelve для более эффективного хранения 125 | словарей на жестком диске. 126 | 127 | Пример алгоритма python с использованием словаря: 128 | ```python 129 | # Создаем словарь с некоторыми значениями 130 | my_dict = {'apple': 10, 'orange': 15, 'banana': 20} 131 | 132 | # Выводим все ключи из словаря 133 | print("Все ключи в словаре:") 134 | for key in my_dict: 135 | print(key) 136 | 137 | # Выводим все значения из словаря 138 | print("Все значения в словаре:") 139 | for value in my_dict.values(): 140 | print(value) 141 | 142 | # Выводим все пары ключ-значение из словаря 143 | print("Все пары ключ-значение в словаре:") 144 | for key, value in my_dict.items(): 145 | print(key, "->", value) 146 | 147 | # Удаляем элемент из словаря 148 | del my_dict['banana'] 149 | print("Словарь после удаления элемента:") 150 | print(my_dict) 151 | 152 | # Добавляем новый элемент в словарь 153 | my_dict['pear'] = 25 154 | print("Словарь после добавления нового элемента:") 155 | print(my_dict) 156 | 157 | # Все ключи в словаре: 158 | # apple 159 | # orange 160 | # banana 161 | # Все значения в словаре: 162 | # 10 163 | # 15 164 | # 20 165 | # Все пары ключ-значение в словаре: 166 | # apple -> 10 167 | # orange -> 15 168 | # banana -> 20 169 | # Словарь после удаления элемента: 170 | # {'apple': 10, 'orange': 15} 171 | # Словарь после добавления нового элемента: 172 | # {'apple': 10, 'orange': 15, 'pear': 25} 173 | ``` 174 | 175 | #### Кортежи: 176 | Кортежи – это неизменяемые упорядоченные наборы элементов. Кортежи используются для хранения данных, 177 | которые не должны изменяться в процессе выполнения программы. В алгоритмах, которые имеют дело с множеством данных, 178 | кортежи могут использоваться как структура для хранения пар значений. 179 | 180 | Кортежи (tuples) в Python хранятся в памяти как неизменяемые объекты. Это означает, что когда вы создаете кортеж, вы 181 | не можете изменить его содержимое в будущем. 182 | 183 | Кортежи занимают меньше памяти, чем списки, потому что не имеют дополнительных методов для изменения их содержимого. 184 | Кроме того, кортежи используют только одну ссылку на объект, поэтому они занимают меньше места в памяти. 185 | 186 | Например, если создать список и кортеж с одинаковыми элементами, для кортежа потребуется меньше памяти: 187 | 188 | ```python 189 | import sys 190 | 191 | my_list = [1, 2, 3, 'a', 'b', 'c'] 192 | my_tuple = (1, 2, 3, 'a', 'b', 'c') 193 | 194 | print(sys.getsizeof(my_list)) # Вывод: 88 195 | print(sys.getsizeof(my_tuple)) # Вывод: 64 196 | ``` 197 | 198 | Как видите, размер кортежа почти на треть меньше, чем размер списка. Это связано с тем, что список имеет 199 | дополнительные методы (append, extend, insert, remove), которые могут изменить его размер, в то время как кортеж не 200 | может быть изменен. 201 | 202 | Пример алгоритма python с использованием кортежа: 203 | ```python 204 | ''' 205 | Этот алгоритм определяет кортеж из нескольких элементов, выводит все элементы кортежа, создает новый кортеж 206 | с помощью конкатенации, получает элементы кортежа по индексу, считает количество элементов в кортеже и удаляет кортеж. 207 | ''' 208 | # Определяем кортеж из нескольких элементов 209 | tup1 = ('apple', 'banana', 'cherry', 'orange', 'peach') 210 | 211 | # Выводим все элементы кортежа 212 | for item in tup1: 213 | print(item) 214 | 215 | # Определяем новый кортеж посредством конкатенации 216 | tup2 = tup1 + ('grape', 'kiwi') 217 | 218 | # Выводим новый кортеж 219 | print(tup2) 220 | 221 | # Получаем элементы кортежа по индексу 222 | print(tup1[0]) 223 | print(tup1[2]) 224 | 225 | # Считаем количество элементов в кортеже 226 | print(len(tup1)) 227 | 228 | # Удаляем кортеж 229 | del tup2 230 | ``` 231 | 232 | #### Множества: 233 | Множества – это структуры данных, которые представляют собой неупорядоченные наборы элементов без 234 | повторений. Множества часто используются в алгоритмах проверки уникальности элементов или для нахождения пересечения 235 | и объединения множеств. 236 | 237 | В Python множества (set) имеют переменный размер, что означает, что они будут использовать сколько-то памяти в 238 | зависимости от количества элементов в них. 239 | 240 | Операция создания множества в Python выделяет некоторую память для хранения элементов множества. Эта память не 241 | освобождается до тех пор, пока множество не будет удалено (удаление происходит при помощи оператора del или после 242 | того, как переменная-ссылка на множество перестанет указывать на него). 243 | 244 | В общем случае, использование множества в Python не является особенно затратным по памяти. Если множество содержит 245 | несколько тысяч элементов или меньше, его размер не должен стать проблемой даже на устройствах с ограниченными 246 | ресурсами. 247 | 248 | Однако, если у вас есть большое количество элементов, то использование множества может привести к большому 249 | потреблению памяти. В этом случае может помочь использование специализированных структур данных, таких как битовые 250 | массивы (bit arrays), которые могут использоваться, если вы работаете с множеством значений из определенного 251 | диапазона, или Bloom filters – наборы хэш-функций, которые могут отвечать на вопрос о том, присутствует ли элемент в 252 | множестве или нет. 253 | 254 | В любом случае, если вы обнаруживаете, что использование множества приводит к проблемам с памятью, наилучшей 255 | стратегией может быть оптимизация алгоритма, который вы используете, или переход на более масштабируемые решения, 256 | использующие например базы данных или хранилища key-value. 257 | 258 | 259 | Пример алгоритма python с использованием множества: 260 | ```python 261 | '''В этом примере создаются два множества, set1 и set2. Оператор & используется для нахождения пересечения множеств, 262 | то есть для поиска элементов, которые содержатся в обоих множествах. Результат пересечения сохраняется в 263 | переменной intersection, а затем выводится на экран с помощью функции print(). 264 | ''' 265 | 266 | # Создание множеств 267 | set1 = set([1, 2, 3, 4]) 268 | set2 = set([3, 4, 5, 6]) 269 | 270 | # Использование оператора пересечения 271 | intersection = set1 & set2 272 | 273 | # Вывод результата на экран 274 | print("Пересечение множеств:", intersection) 275 | ``` 276 | 277 | #### Очереди и стеки: 278 | Очереди и стеки – это структуры данных, которые используются для организации последовательности 279 | элементов. Очереди используются для добавления элементов в хвост очереди и извлечения элементов из головы очереди, а 280 | стеки используются для добавления и извлечения элементов только с одного конца. Очереди и стеки часто используются в 281 | алгоритмах поиска и обхода графов, например в алгоритме поиска в глубину. 282 | 283 | Стек (Stack) - это структура данных, которая позволяет хранить элементы в порядке "последний вошел - первый вышел". 284 | Стеки используются в алгоритмах, где необходимо сохранить последовательность выполнения операций и выполнить их в 285 | обратном порядке. 286 | Пример использования стека в алгоритме: обход дерева в глубину. В данном случае, мы используем стек, чтобы 287 | сохранить последовательность посещения узлов дерева и выполнить их в обратном порядке. Такой подход позволяет 288 | обойти все узлы дерева и выполнить необходимые операции. 289 | 290 | Очередь (Queue) - это структура данных, которая позволяет хранить элементы в порядке "первый вошел - первый вышел". 291 | Очереди используются в алгоритмах, где необходимо сохранить последовательность выполнения операций и выполнить их в 292 | порядке очереди. 293 | Пример использования очереди в алгоритме: алгоритм обхода в ширину в графе. В данном случае, мы используем очередь, 294 | чтобы сохранить последовательность посещения вершин графа и выполнить их в порядке очереди. Это позволяет обойти все 295 | вершины графа и выполнить необходимые операции. 296 | 297 | Массив (Array) - это структура данных, которая позволяет хранить несколько элементов одного типа. Массивы 298 | используются для организации информации, а также для улучшения быстродействия при доступе к элементам. 299 | Пример использования массива в алгоритме: двоичный поиск. Двоичный поиск - это алгоритм поиска элемента в 300 | упорядоченном массиве. Он работает быстрее, чем последовательный поиск, потому что использует принцип деления 301 | массива на половинки и сравнения элемента с значением середины. Таким образом, массив позволяет быстро осуществить 302 | доступ к элементам и выполнить необходимые операции. 303 | 304 | ### Плюсы и минусы использования базовых структур данных Python 305 | Плюсы использования базовых структур данных Python: 306 | - Удобство использования - базовые структуры данных в Python легко создаются и манипулируются. Например, чтобы создать 307 | список, достаточно указать элементы в квадратных скобках. 308 | - Высокая производительность - базовые структуры данных в Python имеют высокую скорость работы, что позволяет быстро 309 | обрабатывать большие объемы данных. 310 | - Разнообразие структур данных - Python поддерживает множество базовых структур данных, включая списки, кортежи, 311 | словари и множества, что позволяет выбрать наиболее подходящую структуру данных для конкретной задачи. 312 | - Широкое использование - базовые структуры данных Python используются в различных областях, от научных исследований 313 | до веб-разработки. 314 | 315 | Минусы использования базовых структур данных Python: 316 | - Низкая эффективность работы с большими объемами данных - при работе с очень большими объемами данных, базовые структуры данных Python могут стать медленными, и потребуется использовать специализированные библиотеки для обработки данных. 317 | - Ограниченная функциональность - базовые структуры данных Python имеют ограниченную функциональность по сравнению со специализированными структурами данных, такими как массивы или деревья. 318 | - Нет поддержки многопоточности - базовые структуры данных Python не могут использоваться эффективно для многопоточных приложений и требуют специализированных библиотек. 319 | - Нарушение инкапсуляции - базовые структуры данных Python не имеют инкапсулированных методов, что может привести к 320 | ошибкам при работе с ними. 321 | 322 | #### Что такое хэш-таблицы и как реализовать хэш-таблицы в Python 323 | Хэш-таблица - это структура данных, которая позволяет эффективно хранить и получать значения по ключу. Она 324 | использует хэш-функцию для преобразования ключа в индекс массива. Каждый индекс в массиве связан с некоторым 325 | значением. Хэш-таблица позволяет быстро находить значения по ключу, используя только одну операцию доступа к памяти. 326 | В Python хэш-таблица реализуется в виде словаря (dict). Внутри словаря данные хранятся в виде пар ключ-значение, где 327 | ключи являются уникальными хэш-значениями, а значения представляют собой соответствующие объекты. 328 | 329 | При добавлении нового элемента в словарь, ключ этого элемента вычисляется с помощью хэш-функции, которая преобразует 330 | произвольную строку или число в уникальное число фиксированной длины. Затем этот ключ используется для индексации 331 | соответствующего места в памяти, где хранится значение. 332 | 333 | Для решения коллизий, т.е. ситуаций, когда два разных ключа имеют одинаковое хэш-значение, Python использует метод 334 | цепочек. При этом для каждого слота в таблице выделяется связный список, в который добавляются элементы с 335 | одинаковыми ключами хэш-функции. Когда количество элементов в списке становится слишком большим, Python 336 | автоматически перестраивает таблицу, увеличивая ее размер. 337 | 338 | Таким образом, хэш-таблица в Python реализована как динамическая структура данных, позволяющая эффективно хранить и 339 | быстро находить элементы по ключу. 340 | 341 | ```python 342 | # В Python реализация хэш-таблицы доступна в виде словарей (dict). Для добавления элемента в словарь используется 343 | # следующий синтаксис: 344 | 345 | my_dict = {} 346 | my_dict[key] = value 347 | 348 | 349 | # Для получения значения по ключу нужно использовать следующий синтаксис: 350 | my_dict[key] 351 | ``` 352 | 353 | Python также позволяет использовать пользовательские классы в качестве ключей в словарях, если эти классы реализуют 354 | методы __hash__() и __eq__(). 355 | 356 | Подробный пример реализации хэш-таблицы в Python: 357 | 358 | ```python 359 | class HashTable: # Создаём класс HashTable 360 | def __init__(self): # Определяем метод __init__ - инициализация или сборка класса 361 | self.size = 11 # определяем размер хэш-таблицы self.size 362 | self.slots = [None] * self.size # массив для ключей self.slots Для начальной инициализации используем None. 363 | self.data = [None] * self.size # массив для значений self.data Для начальной инициализации используем None. 364 | 365 | def put(self, key, data): # Определяем метод put. В нём передаем ключ key и значение data. 366 | '''Определяем хэш-значение ключа hash_value с помощью метода self.hash_function. 367 | ''' 368 | hash_value = self.hash_function(key, len(self.slots)) 369 | 370 | ''' Если на данном хэш-значении в массиве self.slots пусто, 371 | то заполняем соответствующие места ключа и значения новыми значениями.''' 372 | if self.slots[hash_value] is None: 373 | self.slots[hash_value] = key 374 | self.data[hash_value] = data 375 | else: 376 | '''Если на данном хэш-значении уже есть ключ, то заменяем старое значение на новое.''' 377 | if self.slots[hash_value] == key: 378 | self.data[hash_value] = data # replace 379 | else: 380 | '''Если на данном хэш-значении пусто и 381 | это не первоначальная итерация, то находим следующее пустое место в хэш-таблице с помощью метода self.rehash, 382 | который возвращает новое хэш-значение на основе старого (линейное пробирование).''' 383 | next_slot = self.rehash(hash_value, len(self.slots)) 384 | while self.slots[next_slot] is not None and self.slots[next_slot] != key: 385 | next_slot = self.rehash(next_slot, len(self.slots)) 386 | 387 | ''' Если нашёлся свободный слот, то записываем ключ и значение на него.''' 388 | if self.slots[next_slot] is None: 389 | self.slots[next_slot] = key 390 | self.data[next_slot] = data 391 | else: 392 | self.data[next_slot] = data # replace 393 | 394 | def get(self, key): 395 | '''Определяем метод get. В нём передаем ключ key. Определяем начальное позицию start_slot в таблице с 396 | помощью метода self.hash_function. 397 | 398 | ''' 399 | start_slot = self.hash_function(key, len(self.slots)) 400 | 401 | # Создаем переменную для значения data, а также переменные для управления циклом: stop, found и position. 402 | data = None 403 | stop = False 404 | found = False 405 | position = start_slot 406 | while self.slots[position] is not None and not found and not stop: 407 | '''Стартуем цикл. Если на текущей позиции в таблице находится нужный ключ, то 408 | записываем соответствующее значение в переменную data и устанавливаем флаг found в значение True.''' 409 | if self.slots[position] == key: 410 | found = True 411 | data = self.data[position] 412 | else: 413 | '''Если на текущей позиции в таблице находится не нужный ключ, то переходим на следующую позицию с 414 | помощью метода self.rehash.''' 415 | position = self.rehash(position, len(self.slots)) 416 | if position == start_slot: 417 | '''Если дошли до начальной позиции, то выходим из цикла. Возвращаем значение data, которое либо 418 | осталось None, либо содержит нужное значение.''' 419 | stop = True 420 | return data 421 | 422 | def hash_function(self, key, size): 423 | '''Определяем метод hash_function, который принимает ключ key и размер хэш-таблицы size. Возвращает остаток 424 | от деления ключа на размер таблицы. 425 | ''' 426 | return key % size 427 | 428 | def rehash(self, old_hash, size): 429 | '''Определяем метод rehash, который принимает старый хэш old_hash и размер таблицы size. Возвращает новый хэш на основе 430 | текущего, увеличенного на единицу. Если новый хэш больше размера таблицы, то он сбрасывается на ноль. 431 | Применяется линейное пробирование. 432 | ''' 433 | return (old_hash + 1) % size 434 | ``` 435 | 436 | Пример реализации хэш-таблицы в Python: 437 | ```python 438 | ''' 439 | Класс HashTable имеет методы insert, search и delete, которые соответственно позволяют добавлять элементы в 440 | хэш-таблицу, искать их и удалять. Хэш-функция просто берет остаток от деления ключа на размер таблицы. Если в один 441 | слот попадает несколько элементов, они хранятся в виде кортежа (ключ, значение). Если ключ уже есть в таблице при 442 | добавлении, то его значение заменяется новым. При поиске элемента, хэш-таблица вычисляет для него значение 443 | хэш-функции и итерируется по соответствующему слоту, пока не находится элемент с нужным ключом. При удалении 444 | элемента происходит аналогичный поиск, и если элемент найден, он удаляется из слота. 445 | ''' 446 | class HashTable: 447 | def __init__(self, size=10): 448 | self.size = size 449 | self.table = [[] for _ in range(self.size)] 450 | 451 | def _hash_function(self, key): 452 | return key % self.size 453 | 454 | def insert(self, key, value): 455 | hash_value = self._hash_function(key) 456 | slot = self.table[hash_value] 457 | for i, (k, v) in enumerate(slot): 458 | if k == key: 459 | slot[i] = (key, value) 460 | break 461 | else: 462 | slot.append((key, value)) 463 | 464 | def search(self, key): 465 | hash_value = self._hash_function(key) 466 | slot = self.table[hash_value] 467 | for k, v in slot: 468 | if k == key: 469 | return v 470 | raise KeyError(key) 471 | 472 | def delete(self, key): 473 | hash_value = self._hash_function(key) 474 | slot = self.table[hash_value] 475 | for i, (k, v) in enumerate(slot): 476 | if k == key: 477 | del slot[i] 478 | break 479 | else: 480 | raise KeyError(key) 481 | ``` 482 | 483 | #### Приоритетные очереди и способы их реализации 484 | Чтобы понять приоритетные очереди в Python, нам нужно сначала понять, что такое очередь. 485 | 486 | Очередь — это структура данных, в которой элементы хранятся в порядке «первым поступил — первым обслужен» (FIFO). 487 | Это означает, что первый элемент, добавленный в очередь, будет первым элементом, который будет удален. Очереди могут 488 | быть реализованы с помощью списков или очередей в Python. 489 | 490 | Теперь приоритетная очередь — это разновидность очереди, в которой каждый элемент имеет связанный с ним приоритет. 491 | Элементы удаляются из очереди в порядке их приоритета, а не в порядке их добавления. Другими словами, элемент с 492 | наивысшим приоритетом удаляется первым. 493 | 494 | В Python мы можем реализовать приоритетную очередь, используя модуль heapq, который предоставляет функции для 495 | создания структур данных кучи и управления ими. Куча — это двоичная древовидная структура, в которой каждый узел 496 | имеет значение приоритета, а его дочерние элементы имеют значения приоритета, которые ниже или равны родительскому 497 | узлу. 498 | 499 | Модуль heapq предоставляет такие функции, как heappush для добавления элемента в очередь приоритетов, heappop для 500 | удаления элемента с наивысшим приоритетом и heapreplace для замены элемента с наивысшим приоритетом новым элементом. 501 | 502 | Прежде всего, в Python существуют несколько способов реализации приоритетных очередей: 503 | 504 | - Использование встроенного модуля heapq 505 | - Использование классической реализации на основе двоичной кучи (binary heap) 506 | - Использование модуля queue с аргументом PriorityQueue 507 | Для примера кода и дальнейшего описания выберем первый способ - использование модуля heapq. 508 | ```python 509 | '''В этом примере мы создаем список чисел, который затем преобразуем в кучу с помощью функции heapq.heapify(). Затем 510 | мы поочередно извлекаем элементы из кучи с помощью функции heapq.heappop(), которая всегда извлекает минимальный 511 | элемент. 512 | ''' 513 | import heapq 514 | 515 | # Создаем некоторые данные 516 | data = [5, 3, 7, 1, 2, 8, 4] 517 | 518 | # Преобразуем список в кучу (heap) 519 | heapq.heapify(data) 520 | 521 | # Извлекаем элементы из кучи 522 | while data: 523 | print(heapq.heappop(data)) 524 | ``` 525 | 526 | ```python 527 | import heapq 528 | 529 | # создадим пустую кучу 530 | heap = [] 531 | 532 | # добавить элементы в кучу со значениями приоритета 533 | heapq.heappush(heap, (1, 'first element')) 534 | heapq.heappush(heap, (3, 'third element')) 535 | heapq.heappush(heap, (2, 'second element')) 536 | 537 | # удалим элементы из кучи по приоритету 538 | print(heapq.heappop(heap)) # (1, 'first element') 539 | print(heapq.heappop(heap)) # (2, 'second element') 540 | print(heapq.heappop(heap)) # (3, 'third element') 541 | ``` 542 | 543 | ### Знание расширенных структур данных 544 | #### B-дерево 545 | B-дерево - это структура данных, которая используется для хранения и упорядочения больших объемов данных. Оно 546 | является сбалансированным деревом, то есть каждая ветвь содержит примерно одинаковое число элементов. Особенностью 547 | B-дерева является наличие нескольких ключей на узле, что позволяет улучшить эффективность поиска данных. 548 | Б-дерево - это сбалансированное дерево поиска, которое предназначено для уменьшения количества обращений к диску при 549 | поиске данных на жестком диске. Оно состоит из узлов разного размера, которые хранят ключи и ссылки на другие узлы. 550 | 551 | 552 | Пример реализации B-дерева на языке Python: 553 | ```python 554 | '''Это минимальная реализация классов BNode и BTree на Python. Она позволяет вставлять новые элементы в дерево и 555 | выводить его содержимое на экран. В данной реализации используется параметр t, который определяет минимальное 556 | количество ключей на узле. 557 | ''' 558 | class BNode: 559 | def __init__(self, leaf=False): 560 | self.leaf = leaf 561 | self.keys = [] 562 | self.child = [] 563 | 564 | 565 | class BTree: 566 | def __init__(self, t): 567 | self.root = BNode(True) 568 | self.t = t 569 | 570 | def insert(self, k): 571 | root = self.root 572 | if len(root.keys) == (2 * self.t) - 1: 573 | new_root = BNode() 574 | self.root = new_root 575 | new_root.child.insert(0, root) 576 | self._split(new_root, 0) 577 | self._insert_non_full(new_root, k) 578 | else: 579 | self._insert_non_full(root, k) 580 | 581 | def _insert_non_full(self, node, k): 582 | i = len(node.keys) - 1 583 | if node.leaf: 584 | node.keys.append(0) 585 | while i >= 0 and k < node.keys[i]: 586 | node.keys[i+1] = node.keys[i] 587 | i -= 1 588 | node.keys[i+1] = k 589 | else: 590 | while i >= 0 and k < node.keys[i]: 591 | i -= 1 592 | if len(node.child[i+1].keys) == (2*self.t)-1: 593 | self._split(node, i+1) 594 | if k > node.keys[i+1]: 595 | i += 1 596 | self._insert_non_full(node.child[i+1], k) 597 | 598 | def _split(self, node, i): 599 | t = self.t 600 | y = node.child[i] 601 | z = BNode(y.leaf) 602 | node.child.insert(i+1, z) 603 | node.keys.insert(i, y.keys[t-1]) 604 | z.keys = y.keys[t:(2*t)-1] 605 | y.keys = y.keys[0:t-1] 606 | z.child = y.child[t:(2*t)] 607 | y.child = y.child[0:t-1] 608 | 609 | def print_tree(self, node=None, level=0): 610 | if node is None: 611 | node = self.root 612 | 613 | print('Level', level, '->', len(node.keys), end=":") 614 | for i in node.keys: 615 | print(i, end=' ') 616 | print() 617 | 618 | if not node.leaf: 619 | for i in node.child: 620 | self.print_tree(i, level + 1) 621 | ``` 622 | 623 | 624 | 625 | Вот пример реализации Б-дерева и его использования на Python: 626 | ```python 627 | '''В этом коде мы определяем класс «BTreeNode», который представляет собой узел Б-дерева. Узел содержит список 628 | ключей и ссылки на другие узлы. Класс «BTree» представляет собой само дерево. Метод «insert» вставляет новый ключ в 629 | дерево, метод «_split_child» разделяет узел и метод «_insert_nonfull» вставляет новый ключ в неполный узел. ''' 630 | class BTreeNode: 631 | def __init__(self, leaf=False): 632 | self.leaf = leaf 633 | self.keys = [] 634 | self.child = [] 635 | 636 | class BTree: 637 | def __init__(self, degree): 638 | self.root = BTreeNode(True) 639 | self.degree = degree 640 | 641 | def insert(self, k): 642 | r = self.root 643 | if len(r.keys) == (2*self.degree)-1: 644 | s = BTreeNode() 645 | self.root = s 646 | s.child.insert(0, r) 647 | self._split_child(s, 0) 648 | self._insert_nonfull(s, k) 649 | else: 650 | self._insert_nonfull(r, k) 651 | 652 | def _insert_nonfull(self, x, k): 653 | i = len(x.keys)-1 654 | if x.leaf: 655 | x.keys.append(0) 656 | while i >= 0 and k < x.keys[i]: 657 | x.keys[i+1] = x.keys[i] 658 | i -= 1 659 | x.keys[i+1] = k 660 | else: 661 | while i >= 0 and k < x.keys[i]: 662 | i -= 1 663 | i += 1 664 | if len(x.child[i].keys) == (2*self.degree)-1: 665 | self._split_child(x, i) 666 | if k > x.keys[i]: 667 | i += 1 668 | self._insert_nonfull(x.child[i], k) 669 | 670 | def _split_child(self, x, i): 671 | t = self.degree 672 | y = x.child[i] 673 | z = BTreeNode(leaf=y.leaf) 674 | 675 | x.child.insert(i+1, z) 676 | x.keys.insert(i, y.keys[t-1]) 677 | 678 | z.keys = y.keys[t:(2*t)-1] 679 | y.keys = y.keys[0:t-1] 680 | 681 | if not y.leaf: 682 | z.child = y.child[t:(2*t)] 683 | y.child = y.child[0:t-1] 684 | 685 | def search(self, k, x=None): 686 | if isinstance(x, BTreeNode): 687 | i = 0 688 | while i < len(x.keys) and k > x.keys[i]: 689 | i += 1 690 | if i < len(x.keys) and k == x.keys[i]: 691 | return x, i 692 | elif x.leaf: 693 | return None 694 | else: 695 | return self.search(k, x.child[i]) 696 | else: 697 | return self.search(k, self.root) 698 | 699 | def __str__(self): 700 | r = self.root 701 | return self._to_string(r) 702 | 703 | def _to_string(self, x, lvl=0): 704 | ret = " " * lvl 705 | if x is None: 706 | return ret + "None\n" 707 | else: 708 | if x.leaf: 709 | ret += "Leaf -> " 710 | else: 711 | ret += "Node -> " 712 | ret += str(x.keys) + "\n" 713 | for i in range(len(x.child)): 714 | ret += self._to_string(x.child[i], lvl + 1) 715 | return ret 716 | 717 | '''В этом примере мы создаем Б-дерево с минимальной степенью 3 и вставляем несколько ключей в дерево. Затем мы 718 | выполняем поиск ключей в дереве с помощью метода «search». Если ключ находится в дереве, метод «search» возвращает 719 | узел и индекс ключа в этом узле. Если ключ не найден, метод возвращает значение None. 720 | ''' 721 | t = BTree(3) 722 | t.insert(8) 723 | t.insert(18) 724 | t.insert(2) 725 | t.insert(1) 726 | t.insert(20) 727 | t.insert(50) 728 | t.insert(23) 729 | 730 | print(t.search(2)) 731 | print(t.search(23)) 732 | print(t.search(300)) 733 | ``` 734 | 735 | #### Биномиальная куча 736 | Биномиальная куча (binomial heap) - это структура данных, которая представляет собой лес биномиальных деревьев. Она 737 | позволяет эффективно добавлять, удалять и обновлять элементы, а также искать минимальный элемент. 738 | 739 | Биномиальный лес – это семейство биномиальных деревьев. 740 | 741 | Биномиальное дерево высоты h = 0 состоит из одной единственной вершины, биномиальное дерево Bk высоты h = k 742 | образуется присоединением биномиального дерева высоты k-1 к корню другого биномиального дерева высоты k-1. Ниже 743 | показаны биномиальные деревья B0, B1, B2, B3 и B4. 744 | 745 | Bot logo 746 | 747 | Ниже приведена простая реализация биномиальной кучи на языке Python. 748 | ```python 749 | '''В этой реализации биномиальной кучи используется вложенный класс Node, который представляет вершину биномиального 750 | дерева. Куча хранится как односвязный список биномиальных деревьев в порядке убывания их размеров. Операция 751 | объединения двух биномиальных деревьев происходит с помощью рекурсивного объединения их корневых списков. Операция 752 | удаления минимального элемента происходит поиском минимального узла в списке и его последующим удалением. 753 | ''' 754 | class BinomialHeap: 755 | class Node: 756 | def __init__(self, key, value): 757 | self.key = key 758 | self.value = value 759 | self.degree = 0 760 | self.parent = None 761 | self.child = None 762 | self.sibling = None 763 | 764 | def __init__(self): 765 | self.head = None 766 | 767 | def push(self, key, value): 768 | new_node = self.Node(key, value) 769 | self.head = self._merge_lists(self.head, new_node) 770 | 771 | def pop(self): 772 | if not self.head: 773 | return None 774 | 775 | min_node = self.head 776 | prev_node = None 777 | curr_node = min_node 778 | 779 | while curr_node.sibling: 780 | if curr_node.sibling.key < min_node.key: 781 | min_node = curr_node.sibling 782 | prev_node = curr_node 783 | curr_node = curr_node.sibling 784 | 785 | if prev_node: 786 | prev_node.sibling = min_node.sibling 787 | elif min_node == self.head: 788 | self.head = min_node.sibling 789 | 790 | child_head = min_node.child 791 | if child_head: 792 | child_head.parent = None 793 | curr_node = child_head 794 | while curr_node: 795 | next_node = curr_node.sibling 796 | curr_node.sibling = curr_node.parent = None 797 | self.head = self._merge_lists(self.head, curr_node) 798 | curr_node = next_node 799 | 800 | return min_node.value 801 | 802 | def peek(self): 803 | return self.head.value if self.head else None 804 | 805 | def _merge_lists(self, head1, head2): 806 | if not head1: 807 | return head2 808 | if not head2: 809 | return head1 810 | 811 | if head1.key < head2.key: 812 | head1.sibling = self._merge_lists(head1.sibling, head2) 813 | return head1 814 | else: 815 | head2.sibling = self._merge_lists(head2.sibling, head1) 816 | return head2 817 | ``` 818 | 819 | #### Фибоначчиева куча 820 | Фибоначчиева куча (англ. Fibonacci heap) — структура данных, представляющая собой набор деревьев, упорядоченных в 821 | соответствии со свойством неубывающей пирамиды. Фибоначчиевы кучи были введены Майклом Фредманом и Робертом 822 | Тарьяном в 1984 году. 823 | 824 | Структура является реализацией абстрактного типа данных «Очередь с приоритетом», и замечательна тем, что операции, 825 | в которых не требуется удаление, имеют амортизированное время работы. Кроме стандартных операций INSERT, MIN, 826 | DECREASE-KEY, фибоначчиева куча позволяет за время равное время выполнять операцию UNION слияния двух куч. 827 | 828 | ```python 829 | '''Вы можете использовать функцию fibonacci_heap() для создания новой кучи Фибоначчи. Затем вы можете выполнить 830 | операции вставки и удаления элементов из кучи. Например, для вставки элемента используйте метод insert(val), а для 831 | извлечения минимального элемента - метод extract_min(). ''' 832 | def fibonacci_heap(): 833 | class Node: 834 | def __init__(self, val): 835 | self.val = val 836 | self.child = None 837 | self.left = None 838 | self.right = None 839 | self.marked = False 840 | self.degree = 0 841 | self.parent = None 842 | 843 | def __str__(self): 844 | return str(self.val) 845 | 846 | class FibonacciHeap: 847 | def __init__(self): 848 | self.min = None 849 | self.trees = [] 850 | self.num_nodes = 0 851 | 852 | def insert(self, val): 853 | node = Node(val) 854 | if self.min == None: 855 | self.min = node 856 | else: 857 | self._add_to_root_list(node) 858 | if node.val < self.min.val: 859 | self.min = node 860 | self.num_nodes += 1 861 | 862 | def _add_to_root_list(self, node): 863 | node.left = None 864 | node.right = None 865 | self.trees.append(node) 866 | 867 | def extract_min(self): 868 | z = self.min 869 | if z != None: 870 | for c in z.child: 871 | self._add_to_root_list(c) 872 | c.parent = None 873 | self.trees.remove(z) 874 | self.num_nodes -= 1 875 | if z == z.right: 876 | self.min = None 877 | else: 878 | self.min = z.right 879 | self._consolidate() 880 | return z 881 | 882 | def _consolidate(self): 883 | A = [None] * self.num_nodes 884 | for i in range(len(self.trees)): 885 | x = self.trees[i] 886 | d = x.degree 887 | while A[d] != None: 888 | y = A[d] 889 | if x.val > y.val: 890 | temp = x 891 | x = y 892 | y = temp 893 | self._fib_heap_link(y, x) 894 | A[d] = None 895 | d += 1 896 | A[d] = x 897 | self.min = None 898 | for i in range(len(A)): 899 | if A[i] != None: 900 | if self.min == None: 901 | self.trees = [] 902 | self.min = A[i] 903 | else: 904 | self._add_to_root_list(A[i]) 905 | if A[i].val < self.min.val: 906 | self.min = A[i] 907 | 908 | def _fib_heap_link(self, y, x): 909 | self.trees.remove(y) 910 | y.left = y 911 | y.right = y 912 | y.parent = x 913 | x.degree += 1 914 | if x.child == None: 915 | x.child = y 916 | else: 917 | self._add_to_child_list(x.child, y) 918 | y.marked = False 919 | 920 | def _add_to_child_list(self, parent, child): 921 | child.left = parent.left 922 | child.right = parent 923 | parent.left.right = child 924 | parent.left = child 925 | 926 | return FibonacciHeap() 927 | 928 | '''Например, чтобы создать новую кучу Фибоначчи и вставить в нее элементы 5, 3 и 8''' 929 | heap = fibonacci_heap() 930 | 931 | heap.insert(5) 932 | heap.insert(3) 933 | heap.insert(8) 934 | 935 | '''А затем, чтобы извлечь минимальный элемент из кучи, выполните следующую команду''' 936 | min = heap.extract_min() 937 | print(min) 938 | '''Результатом этой команды будет строка "3", так как 3 является минимальным элементом в куче.''' 939 | ``` 940 | 941 | #### АВЛ-дерево 942 | АВЛ-дерево — сбалансированное по высоте двоичное дерево поиска: для каждой его вершины высота её двух поддеревьев 943 | различается не более чем на 1, имеет высокую эффективность при выполнении операций поиска, 944 | добавления и удаления элементов. 945 | 946 | АВЛ — аббревиатура, образованная первыми буквами создателей (советских учёных) Адельсон-Вельского Георгия 947 | Максимовича и Ландиса Евгения Михайловича. 948 | 949 | avltree 950 | 951 | Для создания AVL-дерева в Python мы используем классы. Каждый узел дерева определяется в виде объекта с тремя 952 | свойствами: значение (value), левым (left) и правым (right) потомком. 953 | 954 | Код создания класса для AVL-дерева может выглядеть следующим образом: 955 | ```python 956 | class Node: 957 | def __init__(self, value): 958 | self.value = value 959 | self.left = None 960 | self.right = None 961 | self.height = 1 962 | 963 | 964 | class AVL_Tree: 965 | def __init__(self): 966 | self.root = None 967 | 968 | # Метод для вставки нового элемента в дерево 969 | def insert(self, value): 970 | self.root = self._insert(self.root, value) 971 | 972 | def _insert(self, node, value): 973 | if not node: 974 | return Node(value) 975 | elif value < node.value: 976 | node.left = self._insert(node.left, value) 977 | else: 978 | node.right = self._insert(node.right, value) 979 | 980 | node.height = 1 + max(self._height(node.left), self._height(node.right)) 981 | 982 | balance = self._balance(node) 983 | 984 | if balance > 1 and value < node.left.value: 985 | return self._rotate_right(node) 986 | 987 | if balance < -1 and value > node.right.value: 988 | return self._rotate_left(node) 989 | 990 | if balance > 1 and value > node.left.value: 991 | node.left = self._rotate_left(node.left) 992 | return self._rotate_right(node) 993 | 994 | if balance < -1 and value < node.right.value: 995 | node.right = self._rotate_right(node.right) 996 | return self._rotate_left(node) 997 | 998 | return node 999 | 1000 | # Метод для удаления элемента из дерева 1001 | def delete(self, value): 1002 | self.root = self._delete(self.root, value) 1003 | 1004 | def _delete(self, node, value): 1005 | if not node: 1006 | return node 1007 | 1008 | elif value < node.value: 1009 | node.left = self._delete(node.left, value) 1010 | 1011 | elif value > node.value: 1012 | node.right = self._delete(node.right, value) 1013 | 1014 | else: 1015 | if node.left is None: 1016 | temp = node.right 1017 | node = None 1018 | return temp 1019 | 1020 | elif node.right is None: 1021 | temp = node.left 1022 | node = None 1023 | return temp 1024 | 1025 | temp = self._min_value_node(node.right) 1026 | node.value = temp.value 1027 | node.right = self._delete(node.right, temp.value) 1028 | 1029 | if node is None: 1030 | return node 1031 | 1032 | node.height = 1 + max(self._height(node.left), self._height(node.right)) 1033 | 1034 | balance = self._balance(node) 1035 | 1036 | if balance > 1 and self._balance(node.left) >= 0: 1037 | return self._rotate_right(node) 1038 | 1039 | if balance < -1 and self._balance(node.right) <= 0: 1040 | return self._rotate_left(node) 1041 | 1042 | if balance > 1 and self._balance(node.left) < 0: 1043 | node.left = self._rotate_left(node.left) 1044 | return self._rotate_right(node) 1045 | 1046 | if balance < -1 and self._balance(node.right) > 0: 1047 | node.right = self._rotate_right(node.right) 1048 | return self._rotate_left(node) 1049 | 1050 | return node 1051 | 1052 | # Метод для проверки сбалансированности дерева 1053 | def _balance(self, node): 1054 | if not node: 1055 | return 0 1056 | 1057 | return self._height(node.left) - self._height(node.right) 1058 | 1059 | # Метод для нахождения высоты дерева 1060 | def _height(self, node): 1061 | if not node: 1062 | return 0 1063 | 1064 | return node.height 1065 | 1066 | # Метод для выполнения левого поворота 1067 | def _rotate_left(self, node): 1068 | y = node.right 1069 | z = y.left 1070 | 1071 | y.left = node 1072 | node.right = z 1073 | 1074 | node.height = 1 + max(self._height(node.left), self._height(node.right)) 1075 | y.height = 1 + max(self._height(y.left), self._height(y.right)) 1076 | 1077 | return y 1078 | 1079 | # Метод для выполнения правого поворота 1080 | def _rotate_right(self, node): 1081 | y = node.left 1082 | z = y.right 1083 | 1084 | y.right = node 1085 | node.left = z 1086 | 1087 | node.height = 1 + max(self._height(node.left), self._height(node.right)) 1088 | y.height = 1 + max(self._height(y.left), self._height(y.right)) 1089 | 1090 | return y 1091 | 1092 | # Метод для нахождения узла с минимальным значением 1093 | def _min_value_node(self, node): 1094 | current = node 1095 | 1096 | while current.left is not None: 1097 | current = current.left 1098 | 1099 | return current 1100 | 1101 | ``` 1102 | 1103 | #### Красно-чёрное дерево 1104 | Красно-чёрное дерево (англ. red-black tree, RB tree) — один из видов самобалансирующихся двоичных деревьев поиска, 1105 | гарантирующих логарифмический рост высоты дерева от числа узлов и позволяющее быстро выполнять основные операции 1106 | дерева поиска: добавление, удаление и поиск узла. Сбалансированность достигается за счёт введения дополнительного 1107 | атрибута узла дерева — «цвета». Этот атрибут может принимать одно из двух возможных значений — «чёрный» или 1108 | «красный». 1109 | 1110 | Изобретателем красно-чёрного дерева считают немца Рудольфа Байера. Название «красно-чёрное дерево» структура данных 1111 | получила в статье Л. Гимбаса и Р. Седжвика (1978). По словам Гимбаса, они использовали ручки двух цветов. По 1112 | словам Седжвика, красный цвет лучше всех смотрелся на лазерном принтере. 1113 | 1114 | Красно-чёрное дерево используется для организации сравнимых данных, таких как фрагменты текста или числа. Листовые 1115 | узлы красно-чёрных деревьев не содержат данных, благодаря чему не требуют выделения памяти — достаточно записать в 1116 | узле-предке в качестве указателя на потомка нулевой указатель. Однако в некоторых реализациях для упрощения 1117 | алгоритма могут использоваться явные листовые узлы. 1118 | 1119 | rbtree 1120 | 1121 | Красно-чёрное дерево является структурой данных, представляющей собой бинарное дерево поиска, также известное как 1122 | 2-3-4 дерево или симметричное мультипликативное дерево, используемой для хранения и 1123 | упорядочивания элементов, и который обладает следующими свойствами: 1124 | 1125 | - Каждый узел может быть красным или черным. 1126 | - Корень дерева всегда черный. 1127 | - Каждый лист дерева (NULL) также является черным. 1128 | - Если узел красный, то его дочерние узлы должны быть черными (обратное правило может быть нарушено). 1129 | - Для каждого узла все пути от него до листьев содержат одинаковое количество черных узлов. 1130 | 1131 | Код на Python для красно-черного дерева: 1132 | 1133 | ```python 1134 | class Node(object): 1135 | """Узел дерева""" 1136 | def __init__(self, key, color="red"): 1137 | self.key = key 1138 | self.left = None 1139 | self.right = None 1140 | self.parent = None 1141 | self.color = color 1142 | 1143 | class RedBlackTree(object): 1144 | """Красно-черное дерево""" 1145 | def __init__(self): 1146 | self.nil = Node(None, "black") 1147 | self.nil.left = self.nil.right = self.nil.parent = self.nil 1148 | self.root = self.nil 1149 | 1150 | def insert(self, key): 1151 | """Добавление элемента""" 1152 | new_node = Node(key) 1153 | y = self.nil 1154 | x = self.root 1155 | # Поиск места вставки нового узла 1156 | while x != self.nil: 1157 | y = x 1158 | if new_node.key < x.key: 1159 | x = x.left 1160 | else: 1161 | x = x.right 1162 | new_node.parent = y 1163 | if y == self.nil: 1164 | self.root = new_node 1165 | elif new_node.key < y.key: 1166 | y.left = new_node 1167 | else: 1168 | y.right = new_node 1169 | new_node.left = new_node.right = self.nil 1170 | new_node.color = "red" 1171 | self.insert_fixup(new_node) 1172 | 1173 | def insert_fixup(self, z): 1174 | """Восстановление свойств дерева""" 1175 | while z.parent.color == "red": 1176 | if z.parent == z.parent.parent.left: 1177 | y = z.parent.parent.right 1178 | if y.color == "red": 1179 | z.parent.color = y.color = "black" 1180 | z.parent.parent.color = "red" 1181 | z = z.parent.parent 1182 | else: 1183 | if z == z.parent.right: 1184 | z = z.parent 1185 | self.left_rotate(z) 1186 | z.parent.color = "black" 1187 | z.parent.parent.color = "red" 1188 | self.right_rotate(z.parent.parent) 1189 | else: 1190 | y = z.parent.parent.left 1191 | if y.color == "red": 1192 | z.parent.color = y.color = "black" 1193 | z.parent.parent.color = "red" 1194 | z = z.parent.parent 1195 | else: 1196 | if z == z.parent.left: 1197 | z = z.parent 1198 | self.right_rotate(z) 1199 | z.parent.color = "black" 1200 | z.parent.parent.color = "red" 1201 | self.left_rotate(z.parent.parent) 1202 | self.root.color = "black" 1203 | 1204 | def left_rotate(self, x): 1205 | """Левый поворот""" 1206 | y = x.right 1207 | x.right = y.left 1208 | if y.left != self.nil: 1209 | y.left.parent = x 1210 | y.parent = x.parent 1211 | if x.parent == self.nil: 1212 | self.root = y 1213 | elif x == x.parent.left: 1214 | x.parent.left = y 1215 | else: 1216 | x.parent.right = y 1217 | y.left = x 1218 | x.parent = y 1219 | 1220 | def right_rotate(self, x): 1221 | """Правый поворот""" 1222 | y = x.left 1223 | x.left = y.right 1224 | if y.right != self.nil: 1225 | y.right.parent = x 1226 | y.parent = x.parent 1227 | if x.parent == self.nil: 1228 | self.root = y 1229 | elif x == x.parent.right: 1230 | x.parent.right = y 1231 | else: 1232 | x.parent.left = y 1233 | y.right = x 1234 | x.parent = y 1235 | 1236 | def delete(self, key): 1237 | """Удаление элемента""" 1238 | z = self.search(key) 1239 | if z != self.nil: 1240 | y = z 1241 | y_original_color = y.color 1242 | if z.left == self.nil: 1243 | x = z.right 1244 | self.transplant(z, z.right) 1245 | elif z.right == self.nil: 1246 | x = z.left 1247 | self.transplant(z, z.left) 1248 | else: 1249 | y = self.minimum(z.right) 1250 | y_original_color = y.color 1251 | x = y.right 1252 | if y.parent == z: 1253 | x.parent = y 1254 | else: 1255 | self.transplant(y, y.right) 1256 | y.right = z.right 1257 | y.right.parent = y 1258 | self.transplant(z, y) 1259 | y.left = z.left 1260 | y.left.parent = y 1261 | y.color = z.color 1262 | if y_original_color == "black": 1263 | self.delete_fixup(x) 1264 | 1265 | def delete_fixup(self, x): 1266 | """Восстановление свойств дерева""" 1267 | while x != self.root and x.color == "black": 1268 | if x == x.parent.left: 1269 | w = x.parent.right 1270 | if w.color == "red": 1271 | w.color = "black" 1272 | x.parent.color = "red" 1273 | self.left_rotate(x.parent) 1274 | w = x.parent.right 1275 | if w.left.color == "black" and w.right.color == "black": 1276 | w.color = "red" 1277 | x = x.parent 1278 | else: 1279 | if w.right.color == "black": 1280 | w.left.color = "black" 1281 | w.color = "red" 1282 | self.right_rotate(w) 1283 | w = x.parent.right 1284 | w.color = x.parent.color 1285 | x.parent.color = "black" 1286 | w.right.color = "black" 1287 | self.left_rotate(x.parent) 1288 | x = self.root 1289 | else: 1290 | w = x.parent.left 1291 | if w.color == "red": 1292 | w.color = "black" 1293 | x.parent.color = "red" 1294 | self.right_rotate(x.parent) 1295 | w = x.parent.left 1296 | if w.right.color == "black" and w.left.color == "black": 1297 | w.color = "red" 1298 | x = x.parent 1299 | else: 1300 | if w.left.color == "black": 1301 | w.right.color = "black" 1302 | w.color = "red" 1303 | self.left_rotate(w) 1304 | w = x.parent.left 1305 | w.color = x.parent.color 1306 | x.parent.color = "black" 1307 | w.left.color = "black" 1308 | self.right_rotate(x.parent) 1309 | x = self.root 1310 | x.color = "black" 1311 | 1312 | def transplant(self, u, v): 1313 | """Замена узла""" 1314 | if u.parent == self.nil: 1315 | self.root = v 1316 | elif u == u.parent.left: 1317 | u.parent.left = v 1318 | else: 1319 | u.parent.right = v 1320 | v.parent = u.parent 1321 | 1322 | def search(self, key): 1323 | """Поиск элемента""" 1324 | x = self.root 1325 | while x != self.nil and x.key != key: 1326 | if key < x.key: 1327 | x = x.left 1328 | else: 1329 | x = x.right 1330 | return x 1331 | 1332 | def minimum(self, x=None): 1333 | """Поиск минимального элемента""" 1334 | if x is None: 1335 | x = self.root 1336 | while x.left != self.nil: 1337 | x = x.left 1338 | return x 1339 | 1340 | def maximum(self, x=None): 1341 | """Поиск максимального элемента""" 1342 | if x is None: 1343 | x = self.root 1344 | while x.right != self.nil: 1345 | x = x.right 1346 | return x 1347 | 1348 | def inorder_walk(self, node=None): 1349 | """Обход узлов в порядке возрастания ключей""" 1350 | if node is None: 1351 | node = self.root 1352 | if node != self.nil: 1353 | for x in self.inorder_walk(node.left): 1354 | yield x 1355 | yield node.key 1356 | for x in self.inorder_walk(node.right): 1357 | yield x 1358 | 1359 | def __iter__(self): 1360 | return self.inorder_walk() 1361 | ``` 1362 | 1363 | #### Косое дерево 1364 | Наихудшая временная сложность таких операций, как поиск, удаление и вставка, для двоичного дерева поиска (Binary 1365 | Search Tree) составляет O(n). Наихудший случай случай возникает, когда дерево несбалансировано. Мы можем улучшить 1366 | наихудший результат временной сложности до O(log n) с помощью красно-черных и АВЛ-деревьев. 1367 | 1368 | Можем ли мы добиться на практике лучшего результата, чем тот, что нам дают красно-черные или АВЛ-деревья? 1369 | 1370 | Подобно красно-черным и АВЛ-деревьям, Splay-дерево (или косое дерево) также является самобалансирующимся бинарным 1371 | деревом поиска. Основная идея splay-дерева состоит в том, чтобы помещать элемент, к которому недавно осуществлялся 1372 | доступ, в корень дерева, что делает этот элемент, доступным за время порядка O(1) при повторном доступе. Вся суть 1373 | заключается в том, чтобы использовать концепцию локальности ссылок (в среднестатистическом приложении 80% обращений 1374 | приходятся на 20% элементов). Представьте себе ситуацию, когда у нас есть миллионы или даже миллиарды ключей, и лишь 1375 | к некоторым из них обращаются регулярно, что весьма вероятно для многих типичных приложениях. 1376 | 1377 | Все операции со splay-деревом выполняются в среднем за время порядка O(log n), где n - количество элементов в дереве. 1378 | Любая отдельная операция в худшем случае может занять время порядка Тэта(n). 1379 | 1380 | 1381 | Операция поиска в splay-дереве представляет собой стандартный алгоритм поиска в бинарном дереве, после которого 1382 | дерево выворачивается (искомый узел перемещается в корень — операция splay). Если поиск завершился успехом, то 1383 | найденный узел поднимается наверх и становится новым корнем. В противном случае корнем становится последний узел, к 1384 | которому был осуществлен доступ до достижения NULL. 1385 | 1386 | Расширяющееся (англ. splay tree) или косое дерево является двоичным деревом поиска, в котором поддерживается 1387 | свойство сбалансированности. Это дерево принадлежит классу «саморегулирующихся деревьев», которые поддерживают 1388 | необходимый баланс ветвления дерева, чтобы обеспечить выполнение операций поиска, добавления и удаления за 1389 | логарифмическое время от числа хранимых элементов. Это реализуется без использования каких-либо дополнительных полей 1390 | в узлах дерева (как, например, в Красно-чёрных деревьях или АВЛ-деревьях, где в вершинах хранится, соответственно, 1391 | цвет вершины и глубина поддерева). Вместо этого «расширяющие операции» (splay operation), частью которых являются 1392 | вращения, выполняются при каждом обращении к дереву. 1393 | 1394 | 1395 | Расширяющееся дерево придумали Роберт Тарьян и Даниель Слейтор в 1983 году. 1396 | 1397 | ```python 1398 | class Node: 1399 | def __init__(self, value): 1400 | self.value = value 1401 | self.left_child = None 1402 | self.right_child = None 1403 | 1404 | class SkewedBinaryTree: 1405 | def __init__(self, values): 1406 | self.root = None 1407 | self.build_tree(values) 1408 | 1409 | def build_tree(self, values): 1410 | for value in values: 1411 | node = Node(value) 1412 | if self.root is None: 1413 | self.root = node 1414 | else: 1415 | self.insert_node(node, self.root) 1416 | 1417 | def insert_node(self, node, current_node): 1418 | if node.value > current_node.value: 1419 | if current_node.right_child is None: 1420 | current_node.right_child = node 1421 | else: 1422 | self.insert_node(node, current_node.right_child) 1423 | else: 1424 | if current_node.left_child is None: 1425 | current_node.left_child = node 1426 | else: 1427 | self.insert_node(node, current_node.left_child) 1428 | ``` 1429 | 1430 | #### Список с пропусками 1431 | Список с пропусками (англ. Skip List) — вероятностная структура данных, основанная на нескольких параллельных 1432 | отсортированных связных списках с эффективностью, сравнимой с двоичным деревом (порядка O(log n) среднее время для 1433 | большинства операций). 1434 | 1435 | В основе списка с пропусками лежит расширение отсортированного связного списка дополнительными связями, добавленными 1436 | в случайных путях с геометрическим/негативным биномиальным распределением, таким образом, чтобы поиск по списку 1437 | мог быстро пропускать части этого списка. Вставка, поиск и удаление выполняются за логарифмическое случайное время. 1438 | 1439 | Для создания списка с пропусками в Python можно использовать формирование списка с помощью лист-понимания (list 1440 | comprehension) и функции range(). Например, если требуется создать список с 10 элементами, где каждый второй элемент 1441 | является пропуском, можно написать следующий код: 1442 | 1443 | ```python 1444 | my_list = [i if i % 2 == 0 else None for i in range(10)] 1445 | # Используется функция range() для создания последовательности чисел от 0 до 9. 1446 | # Если число четное, то оно добавляется в список. Если нечетное, то добавляется пропуск (None). 1447 | # Результатом выполнения кода является созданный список с пропусками. 1448 | 1449 | # Таким образом, результатом выполнения этого кода будет список с элементами: 1450 | # [0, None, 2, None, 4, None, 6, None, 8, None]. 1451 | 1452 | ``` 1453 | 1454 | В этом коде используется лист-понимания для создания списка. Функция range(10) возвращает последовательность 1455 | чисел от 0 до 9. Оператор if i % 2 == 0 используется для проверки того, является ли текущий элемент четным числом 1456 | или нет. Если элемент четный, то он добавляется в список, иначе добавляется пропуск (None). 1457 | 1458 | #### Trie, или нагруженное дерево 1459 | Trie, или нагруженное дерево — структура данных реализующая интерфейс ассоциативного массива, то есть позволяющая 1460 | хранить пары «ключ-значение». Сразу следует оговорится, что в большинстве случаев ключами выступают строки, однако в 1461 | качестве ключей можно использовать любые типы данных, представимые как последовательность байт (то есть вообще любые). 1462 | 1463 | 1464 | Нагруженное дерево отличается от обычных n-арных деревьев тем, что в его узлах не хранятся ключи. Вместо них в узлах 1465 | хранятся односимвольные метки, а ключем, который соответствует некоему узлу является путь от корня дерева до этого 1466 | узла, а точнее строка составленная из меток узлов, повстречавшихся на этом пути. В таком случае корень дерева, 1467 | очевидно, соответствует пустому ключу. 1468 | 1469 | TRIE (также известный как префиксное дерево или бор) - это древовидная структура данных для хранения и поиска 1470 | множества строк. Он позволяет выполнять операции поиска, вставки и удаления строк в среднем за время, 1471 | пропорциональное длине строки. Каждый узел дерева содержит один символ строки вместе с указателем на следующий узел 1472 | в этой строке. 1473 | 1474 | Вот пример реализации TRIE в Python: 1475 | ```python 1476 | # Класс Node представляет узел дерева, каждый из которых может иметь несколько дочерних узлов. Атрибут word_end 1477 | # определяет, является ли данный узел концом строки. 1478 | 1479 | 1480 | class Node: 1481 | def __init__(self): 1482 | self.children = {} # словарь дочерних узлов 1483 | self.word_end = False # флаг конца слова 1484 | 1485 | # Класс Trie использует класс Node для создания TRIE. Метод insert вставляет новое слово в TRIE дерево, а методы 1486 | # search и startsWith производят поиск соответствующих слов или префиксов в дереве. 1487 | class Trie: 1488 | def __init__(self): 1489 | self.root = Node() # создаем корень дерева 1490 | 1491 | def insert(self, word: str) -> None: 1492 | node = self.root 1493 | for char in word: 1494 | # если узел для текущего символа не существует, то создаем его 1495 | if char not in node.children: 1496 | node.children[char] = Node() 1497 | node = node.children[char] 1498 | node.word_end = True # помечаем конец слова 1499 | 1500 | def search(self, word: str) -> bool: 1501 | node = self.root 1502 | for char in word: 1503 | if char not in node.children: 1504 | return False 1505 | node = node.children[char] 1506 | return node.word_end # возвращаем True, если слово найдено 1507 | 1508 | def startsWith(self, prefix: str) -> bool: 1509 | node = self.root 1510 | for char in prefix: 1511 | if char not in node.children: 1512 | return False 1513 | node = node.children[char] 1514 | return True # возвращаем True, если существует хотя бы одно слово с таким префиксом 1515 | 1516 | 1517 | # Пример использования: 1518 | 1519 | trie = Trie() 1520 | words = ["apple", "banana", "cat", "dog"] 1521 | 1522 | # вставляем слова в дерево 1523 | for word in words: 1524 | trie.insert(word) 1525 | 1526 | # проверяем, существуют ли слова в дереве 1527 | print(trie.search("banana")) # True 1528 | print(trie.search("elephant")) # False 1529 | 1530 | # проверяем, существуют ли слова с заданным префиксом в дереве 1531 | print(trie.startsWith("ap")) # True 1532 | print(trie.startsWith("d")) # True 1533 | print(trie.startsWith("f")) # False 1534 | 1535 | ``` 1536 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 BEPb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

12 |
13 | 14 | 15 | Bot logo 16 | 17 | 18 | # Programmer Competency Matrix 19 | 20 |
21 | 22 | Read in other languages: [Русский](README.ru.md) 23 | 24 | ## Hi all. 25 | Today is March 13, 2023, and it just so happens that for more than 3 years I have been actively studying python 26 | programming as well as data science. The contract ends in half a year and I decided that it was time to change 27 | activities from a radio engineer to a machine learning specialist. But how to evaluate myself, how to show the 28 | future employer what I know, how I can develop??? Divide and rule (lat. divide et impera) - says the maxim of the 29 | Roman Senate, let's approach the answer to the question asked systematically. Let's separate all the components of 30 | my specialist knowledge and evaluate them using the competence matrix. 31 | 32 | Of course, I didn’t reinvent the wheel and took a ready-made matrix (the most common version was proposed by Sijin 33 | Joseph [here](https://sijinjoseph.netlify.app/programmer-competency-matrix/)) and honestly answered these questions, 34 | the answer was diligently put into separate files. 35 | 36 | #### in progress... 37 | 38 | 39 |
40 | Computer Science 41 |

in progress...

42 | 43 | - [ ] **Data structures** 44 | - [x] Level 0 - Doesn’t know the difference between Array and LinkedList 45 | - [x] Level 1 - Able to explain and use Arrays, LinkedLists, Dictionaries etc in practical programming tasks 46 | - [x] Level 2 - Knows space and time tradeoffs of the basic data structures, Arrays vs LinkedLists, Able to explain 47 | how hashtables can be implemented and can handle collisions, Priority queues and ways to implement them etc. 48 | - [x] Level 3 - Knowledge of advanced data structures like B-trees, binomial and fibonacci heaps, AVL/Red Black trees, 49 | Splay Trees, Skip Lists, tries etc. 50 | 51 | - [ ] **Algorithms** 52 | - [x] Level 0 - Unable to find the average of numbers in an array (It’s hard to believe but I’ve interviewed such candidates) 53 | - [x] Level 1 - Basic sorting, searching and data structure traversal and retrieval algorithms 54 | - [x] Level 2 - Tree, Graph, simple greedy and divide and conquer algorithms, is able to understand the 55 | relevance of the levels of this matrix. 56 | - [ ] Level 3 - Able to recognize and code dynamic programming solutions, good knowledge of graph algorithms, 57 | good knowledge of numerical computation algorithms, able to identify NP problems etc. 58 | 59 | - [ ] **Systems programming** 60 | - [x] Level 0 - Doesn’t know what a compiler, linker or interpreter is 61 | - [x] Level 1 - Basic understanding of compilers, linker and interpreters. Understands what assembly code is and 62 | how things work at the hardware level. Some knowledge of virtual memory and paging. 63 | - [ ] Level 2 - Understands kernel mode vs. user mode, multi-threading, synchronization primitives and how they’re 64 | implemented, able to read assembly code. Understands how networks work, understanding of network protocols and 65 | socket level programming. 66 | - [ ] Level 3 - Understands the entire programming stack, hardware (CPU + Memory + Cache + 67 | Interrupts + microcode), binary code, assembly, static and dynamic linking, compilation, interpretation, JIT 68 | compilation, garbage collection, heap, stack, memory addressing… 69 | 70 |
71 |
72 | Software Engineering 73 | in progress... 74 | 75 | - [ ] **Source code version control** 76 | - [x] Level 0 - Folder backups by date 77 | - [x] Level 1 - VSS and beginning CVS/SVN user 78 | - [x] Level 2 - Proficient in using CVS and SVN features. Knows how to branch and merge, use patches setup repository 79 | properties etc. 80 | - [ ] Level 3 - Knowledge of distributed VCS systems. Has tried out Bzr/Mercurial/Darcs/Git 81 | 82 | - [ ] **Build automation** 83 | - [x] Level 0 - Only knows how to build from IDE 84 | - [x] Level 1 - Knows how to build the system from the command line 85 | - [x] Level 2 - Can setup a script to build the basic system 86 | - [ ] Level 3 - Can setup a script to build the system and also documentation, installers, generate release notes 87 | and tag the code in source control 88 | 89 | - [ ] **Automated testing** 90 | - [x] Level 0 - Thinks that all testing is the job of the tester 91 | - [x] Level 1 - Has written automated unit tests and comes up with good unit test cases for the code that is being written 92 | - [x] Level 2 - Has written code in TDD manner 93 | - [ ] Level 3 - Understands and is able to setup automated functional, load/performance and UI tests 94 | 95 |
96 |
97 | Programming 98 | in progress... 99 | 100 | - [ ] **Problem decomposition** 101 | - [x] Level 0 - Only straight line code with copy paste for reuse 102 | - [x] Level 1 - Able to break up problem into multiple functions 103 | - [x] Level 2 - Able to come up with reusable functions/objects that solve the overall problem 104 | - [ ] Level 3 - Use of appropriate data structures and algorithms and comes up with generic/object-oriented code 105 | that encapsulate aspects of the problem that are subject to change. 106 | 107 | 108 | - [ ] **Systems decomposition** 109 | - [x] Level 0 - Not able to think above the level of a single file/class 110 | - [x] Level 1 - Able to break up problem space and design solution as long as it is within the same platform/technology 111 | - [x] Level 2 - Able to design systems that span multiple technologies/platforms. 112 | - [ ] Level 3 - Able to visualize and design complex systems with multiple product lines and integrations with 113 | external systems. Also should be able to design operations support systems like monitoring, reporting, fail 114 | overs etc. 115 | 116 | - [ ] **Communication** 117 | - [x] Level 0 - Cannot express thoughts/ideas to peers. Poor spelling and grammar. 118 | - [x] Level 1 - Peers can understand what is being said. Good spelling and grammar. 119 | - [x] Level 2 - Is able to effectively communicate with peers 120 | - [ ] Level 3 - Able to understand and communicate thoughts/design/ideas/specs in a unambiguous 121 | manner and adjusts communication as per the context 122 | - This is an often under rated but very critical criteria 123 | for judging a programmer. With the increase in outsourcing of programming tasks to places where English is not 124 | the 125 | native tongue this issue has become more prominent. I know of several projects that failed because the 126 | programmers 127 | could not understand what the intent of the communication was. 128 | 129 | - [ ] **Code organization within a file** 130 | - [x] Level 0 - no evidence of organization within a file 131 | - [x] Level 1 - Methods are grouped logically or by accessibility 132 | - [x] Level 2 - Code is grouped into regions and well commented with references to other source files 133 | - [ ] Level 3 - File has license header, summary, well commented, consistent white space usage. The file should look 134 | beautiful. 135 | 136 | - [ ] **Code organization across files** 137 | - [x] Level 0 - No thought given to organizing code across files 138 | - [x] Level 1 - Related files are grouped into a folder 139 | - [x] Level 2 - Each physical file has a unique purpose, for e.g. one class definition, one feature implementation etc. 140 | - [ ] Level 3 - Code organization at a physical level closely 141 | matches design and looking at file names and folder distribution provides insights into 142 | design 143 | 144 | - [ ] **Source tree organization** 145 | - [x] Level 0 - Everything in one folder 146 | - [x] Level 1 - Basic separation of code into logical folders. 147 | - [x] Level 2 - No circular dependencies, binaries, libs, docs, builds, third-party code all 148 | organized into appropriate folders 149 | - [ ] Level 3 - Physical layout of source tree matches logical hierarchy and organization. 150 | The directory names and organization provide insights into the design of the system. 151 | - The difference between 152 | this and the previous item is in the scale of organization, source tree organization relates to the entire set 153 | of 154 | artifacts that define the system. 155 | 156 | - [ ] **Code readability** 157 | - [x] Level 0 - Mono-syllable names 158 | - [x] Level 1 - Good names for files, variables classes, methods etc. 159 | - [x] Level 2 - No long functions, comments explaining unusual code, bug fixes, 160 | code assumptions 161 | - [ ] Level 3 - Code assumptions are verified using asserts, code flows naturally – no deep nesting of 162 | conditionals or methods 163 | 164 | - [ ] **Defensive coding** 165 | - [x] Level 0 - Doesn’t understand the concept 166 | - [x] Level 1 - Checks all arguments and asserts critical assumptions in code 167 | - [x] Level 2 - Makes sure to check return values and check for exceptions around code that can fail. 168 | - [ ] Level 3 - Has his own library to help with defensive coding, writes unit tests that simulate faults 169 | 170 | - [ ] **Error handling** 171 | - [x] Level 0 - Only codes the happy case 172 | - [x] Level 1 - Basic error handling around code that can throw exceptions/generate errors 173 | - [x] Level 2 - Ensures that error/exceptions leave program in good state, resources, connections and memory is 174 | all cleaned up properly 175 | - [ ] Level 3 - Codes to detect possible exception before, maintain consistent exception handling strategy in all 176 | layers of code, come up with guidelines on exception handling for entire system. 177 | 178 | - [ ] **IDE** 179 | - [x] Level 0 - Mostly uses IDE for text editing 180 | - [x] Level 1 - Knows their way around the interface, 181 | able to effectively use the IDE using menus. 182 | - [x] Level 2 - Knows keyboard shortcuts for most used operations. 183 | - [ ] Level 3 - Has written custom macros 184 | 185 | - [ ] **API** 186 | - [x] Level 0 - Needs to look up the documentation frequently 187 | - [x] Level 1 - Has the most frequently used APIs in memory 188 | - [x] Level 2 - Vast and In-depth knowledge of the API 189 | - [ ] Level 3 - Has written libraries that sit on top of the API to simplify frequently used tasks and to fill in gaps 190 | in the API 191 | - E.g. of API can be Java library, .net framework or the custom API for the 192 | application 193 | 194 | - [ ] **Frameworks** 195 | - [x] Level 0 - Has not used any framework outside of the core platform 196 | - [x] Level 1 - Has heard about but not used the popular frameworks available for the platform. 197 | - [x] Level 2 - Has used more than one framework in a professional capacity and is well-versed with the idioms of 198 | the frameworks. 199 | - [ ] Level 3 - Author of framework 200 | 201 | - [ ] **Requirements** 202 | - [x] Level 0 - Takes the given requirements and codes to spec 203 | - [x] Level 1 - Come up with questions regarding missed cases in the spec 204 | - [x] Level 2 - Understand complete picture and come up with entire areas that need to be speced 205 | - [ ] Level 3 - Able to suggest better alternatives and flows to given requirements based on experience 206 | 207 | - [ ] **Scripting** 208 | - [x] Level 0 - No knowledge of scripting tools 209 | - [x] Level 1 - Batch files/shell scripts 210 | - [x] Level 2 - Perl/Python/Ruby/VBScript/Powershell 211 | - [ ] Level 3 - Has written and published reusable code 212 | 213 | - [ ] **Database** 214 | - [x] Level 0 - Thinks that Excel is a database 215 | - [x] Level 1 - Knows basic database concepts, normalization, ACID, transactions and can write simple selects 216 | - [x] Level 2 - Able to design good and normalized database schemas keeping in mind the queries that’ll have to 217 | be run, proficient in use of views, stored procedures, triggers and user defined types. Knows difference 218 | between clustered and non-clustered indexes. Proficient in use of ORM tools. 219 | - [ ] Level 3 - Can do basic database administration, performance optimization, index optimization, write 220 | advanced select queries, able to replace cursor usage with relational sql, understands how data is stored 221 | internally, understands how indexes are stored internally, understands how databases can be mirrored, 222 | replicated etc. Understands how the two phase commit works. 223 | 224 | 225 |
226 |
227 | Experience 228 | in progress... 229 | 230 | - [ ] **Languages with professional experience** 231 | - [x] Level 0 - Imperative or Object Oriented 232 | - [x] Level 1 - Imperative, Object-Oriented and declarative (SQL), added bonus if they understand static vs dynamic 233 | typing, weak vs strong typing and static inferred types 234 | - [x] Level 2 - Functional, added bonus if they understand lazy 235 | evaluation, currying, continuations 236 | - [ ] Level 3 - Concurrent (Erlang, Oz) and Logic (Prolog) 237 | 238 | 239 | - [ ] **Platforms with professional 240 | experience** 241 | - [x] Level 0 - 1 242 | - [x] Level 1 - 2-3 243 | - [x] Level 2 - 4-5 244 | - [ ] Level 3 - 6+ 245 | 246 | - [ ] **Years of professional experience** 247 | - [x] Level 0 - 1 248 | - [x] Level 1 - 2-5 249 | - [x] Level 2 - 6-9 250 | - [ ] Level 3 - 10+ 251 | 252 | - [ ] **Domain knowledge** 253 | - [x] Level 0 - No knowledge of the domain 254 | - [x] Level 1 - Has worked on at least one product in the domain. 255 | - [x] Level 2 - Has worked on multiple products in the same domain. 256 | - [ ] Level 3 - Domain expert. Has designed and implemented several products/solutions in the 257 | domain. Well versed with standard terms, protocols used in the domain. 258 | 259 |
260 | 261 |
262 | Knowledge 263 | in progress... 264 | 265 | - [ ] **Tool knowledge** 266 | - [x] Level 0 - Limited to primary IDE (VS.Net, Eclipse etc.) 267 | - [x] Level 1 - Knows about some alternatives to popular and standard tools. 268 | - [x] Level 2 - Good knowledge of editors, debuggers, IDEs, open source alternatives etc. etc. For e.g. 269 | someone who knows most of the tools from Scott Hanselman’s power tools list. Has used ORM tools. 270 | - [ ] Level 3 - Has actually written tools and scripts, added bonus if they’ve been published. 271 | 272 | - [ ] **Languages exposed to** 273 | - [x] Level 0 - Imperative or Object Oriented 274 | - [x] Level 1 - Imperative, Object-Oriented and declarative (SQL), added 275 | bonus if they understand static vs dynamic typing, weak vs strong typing and static inferred 276 | types 277 | - [x] Level 2 - Functional, added bonus if they understand lazy evaluation, currying, continuations 278 | - [ ] Level 3 - Concurrent 279 | (Erlang, Oz) and Logic (Prolog) 280 | 281 | - [ ] **Codebase knowledge** 282 | - [x] Level 0 - Has never looked at the codebase 283 | - [x] Level 1 - Basic knowledge of the code layout and how to build the system 284 | - [x] Level 2 - Good working knowledge of code base, has implemented several bug fixes and maybe some small features. 285 | - [ ] Level 3 - Has implemented multiple big features in the codebase and can easily visualize the changes 286 | required for most features or bug fixes. 287 | 288 | - [ ] **Knowledge of upcoming technologies** 289 | - [x] Level 0 - Has not heard of the upcoming technologies 290 | - [x] Level 1 - Has heard of upcoming technologies in the field 291 | - [x] Level 2 - Has downloaded the alpha preview/CTP/beta and read some articles/manuals 292 | - [ ] Level 3 - Has played with the previews and has actually built something with it and as a bonus shared that 293 | with everyone else 294 | 295 | - [ ] **Platform internals** 296 | - [x] Level 0 - Zero knowledge of platform internals 297 | - [x] Level 1 - Has basic knowledge of how the platform works internally 298 | - [x] Level 2 - Deep knowledge of platform internals and can visualize how the platform takes the program and 299 | converts it into executable code. 300 | - [ ] Level 3 - Has written tools to enhance or provide information on platform internals. 301 | For e.g. disassemblers, decompilers, debuggers etc. 302 | 303 | - [ ] **Books** 304 | - [x] Level 0 - Unleashed series, 21 days series, 24 hour series, dummies series… 305 | - [x] Level 1 - Code Complete, Don’t Make me Think, Mastering Regular Expressions 306 | - [x] Level 2 - Design Patterns, Peopleware, Programming Pearls, Algorithm Design Manual, Pragmatic Programmer, 307 | Mythical Man month 308 | - [ ] Level 3 - Structure and Interpretation of Computer Programs, Concepts Techniques, Models of 309 | Computer Programming, Art of Computer Programming, Database systems , by C. J Date, Thinking Forth, Little 310 | Schemer 311 | 312 | - [ ] **Blogs** 313 | - [x] Level 0 - Has heard of them but never got the time. 314 | - [x] Level 1 - Reads tech/programming/software engineering blogs and listens to podcasts regularly. 315 | - [x] Level 2 - Maintains a link blog with some collection of useful articles and tools that he/she has collected 316 | - [ ] Level 3 - Maintains a blog in which personal insights and thoughts on programming are shared 317 | 318 |
319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | --- 329 | 330 |
331 | Full table 332 |

333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 363 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 374 | 377 | 378 | 379 | 380 | <> 381 | 382 | 385 | 390 | 394 | 398 | 399 | 400 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 414 | 415 | 416 | 417 | 418 | 419 | 422 | 423 | 424 | 427 | 430 | 431 | 432 | 433 | 436 | 437 | 440 | 441 | 445 | 446 | 447 | 448 | 449 | 452 | 455 | 456 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 480 | 481 | 482 | 483 | 484 | 487 | 488 | 491 | 494 | 495 | 496 | 497 | 498 | 501 | 504 | 505 | 510 | 511 | 512 | 513 | 514 | 516 | 517 | 520 | 523 | 530 | 531 | 532 | 535 | 536 | 539 | 542 | 545 | 546 | 547 | 548 | 549 | 552 | 553 | 556 | 560 | 561 | 562 | 563 | 564 | 565 | 568 | 571 | 574 | 579 | 580 | 581 | 582 | 583 | 586 | 589 | 592 | 593 | 594 | 595 | 596 | 599 | 600 | 603 | 606 | 607 | 608 | 609 | 610 | 613 | 614 | 618 | 621 | 622 | 623 | 624 | 625 | 626 | 629 | 630 | 633 | 634 | 635 | 636 | 637 | 640 | 641 | 644 | 647 | 650 | 651 | 652 | 653 | 654 | 657 | 660 | 663 | 664 | 665 | 666 | 667 | 668 | 671 | 674 | 677 | 678 | 679 | 680 | 681 | 682 | 685 | 686 | 689 | 690 | 691 | 692 | 693 | 694 | 697 | 704 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 731 | 732 | 733 | 734 | 735 | 738 | 741 | 744 | 746 | 747 | 748 | 749 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 773 | 774 | 777 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 796 | 797 | 800 | 803 | 806 | 807 | 808 | 809 | 812 | 813 | 817 | 818 | 821 | 822 | 823 | 824 | 825 | 828 | 829 | 832 | 835 | 836 | 837 | 838 | 839 | 842 | 843 | 846 | 849 | 850 | 851 | 852 | 855 | 856 | 859 | 862 | 865 | 866 | 867 | 868 | 869 | 872 | 875 | 878 | 882 | 883 | 884 | 885 | 886 | 887 | 890 | 893 | 896 | 897 | 898 | 899 |

Computer Science

(Level 0) (Level 1) (Level 2) (Level 3)Comments
data structuresDoesn’t know the difference between Array and LinkedListAble to explain and use Arrays, LinkedLists, Dictionaries etc in practical programming tasksKnows space and time tradeoffs of the basic data structures, Arrays vs LinkedLists, Able to explain 361 | how hashtables can be implemented and can handle collisions, Priority queues and ways to implement them etc. 362 | Knowledge of advanced data structures like B-trees, binomial and fibonacci heaps, AVL/Red Black trees, 364 | Splay Trees, Skip Lists, tries etc.
algorithmsUnable to find the average of numbers in an array (It’s hard to believe but I’ve interviewed such candidates)Basic sorting, searching and data structure traversal and retrieval algorithmsTree, Graph, simple greedy and divide and conquer 373 | algorithms, is able to understand the relevance of the levels of this matrix.Able to recognize and code 375 | dynamic programming solutions, good knowledge of graph algorithms, good knowledge of numerical computation 376 | algorithms, able to identify NP problems etc.
systems programmingDoesn’t know 383 | what a compiler, linker or interpreter is 384 | Basic understanding of compilers, linker and interpreters. 386 | Understands what assembly code is and how things work at the hardware level. Some knowledge of virtual memory 387 | and 388 | paging. 389 | Understands kernel mode vs. user mode, multi-threading, synchronization primitives and how they’re 391 | implemented, able to read assembly code. Understands how networks work, understanding of network protocols and 392 | socket level programming. 393 | Understands the entire programming stack, hardware (CPU + Memory + Cache + 395 | Interrupts + microcode), binary code, assembly, static and dynamic linking, compilation, interpretation, JIT 396 | compilation, garbage collection, heap, stack, memory addressing… 397 |

Software 401 | Engineering

2n (Level 0)n2 412 | (Level 1) 413 | n (Level 2)log(n) (Level 3)Comments
source code version 420 | control 421 | Folder backups by dateVSS and beginning CVS/SVN userProficient in using CVS and 425 | SVN features. Knows how to branch and merge, use patches setup repository properties etc. 426 | Knowledge of 428 | distributed VCS systems. Has tried out Bzr/Mercurial/Darcs/Git 429 |
build 434 | automation 435 | Only knows how to build from IDEKnows how to build the system from the command 438 | line 439 | Can setup a script to build the basic systemCan setup a script to build the system and also 442 | documentation, installers, generate release notes and tag the code in source 443 | control 444 |
automated testingThinks that all testing is the job of the 450 | tester 451 | Has written automated unit tests and comes up with good unit test cases for the code that is being 453 | written 454 | Has written code in TDD mannerUnderstands and is able to setup automated functional, 457 | load/performance and UI tests 458 |

Programming

2n (Level 0)n2 (Level 1)n (Level 2)log(n) (Level 3) 479 | Comments
problem decompositionOnly straight line code with copy paste for 485 | reuse 486 | Able to break up problem into multiple functionsAble to come up with reusable 489 | functions/objects that solve the overall problem 490 | Use of appropriate data structures and algorithms and comes 492 | up with generic/object-oriented code that encapsulate aspects of the problem that are subject to change. 493 |
systems decompositionNot able to think above the level of a single 499 | file/class 500 | Able to break up problem space and design solution as long as it is within the same 502 | platform/technology 503 | Able to design systems that span multiple technologies/platforms.Able to 506 | visualize and design complex systems with multiple product lines and integrations with external systems. Also 507 | should 508 | be able to design operations support systems like monitoring, reporting, fail overs etc. 509 |
communicationCannot express thoughts/ideas to peers. Poor spelling and grammar. 515 | Peers can understand what is being said. Good spelling and grammar.Is able to effectively 518 | communicate with peers 519 | Able to understand and communicate thoughts/design/ideas/specs in a unambiguous 521 | manner and adjusts communication as per the context 522 | This is an often under rated but very critical criteria 524 | for judging a programmer. With the increase in outsourcing of programming tasks to places where English is not 525 | the 526 | native tongue this issue has become more prominent. I know of several projects that failed because the 527 | programmers 528 | could not understand what the intent of the communication was. 529 |
code organization within a 533 | file 534 | no evidence of organization within a fileMethods are grouped logically or by 537 | accessibility 538 | Code is grouped into regions and well commented with references to other source 540 | files 541 | File has license header, summary, well commented, consistent white space usage. The file should look 543 | beautiful. 544 |
code organization across filesNo thought given to organizing code 550 | across files 551 | Related files are grouped into a folderEach physical file has a unique purpose, for e. 554 | g. one class definition, one feature implementation etc. 555 | Code organization at a physical level closely 557 | matches design and looking at file names and folder distribution provides insights into 558 | design 559 |
source tree organizationEverything in one folderBasic separation 566 | of code into logical folders. 567 | No circular dependencies, binaries, libs, docs, builds, third-party code all 569 | organized into appropriate folders 570 | Physical layout of source tree matches logical hierarchy and organization. 572 | The directory names and organization provide insights into the design of the system. 573 | The difference between 575 | this and the previous item is in the scale of organization, source tree organization relates to the entire set 576 | of 577 | artifacts that define the system. 578 |
code readabilityMono-syllable namesGood names 584 | for files, variables classes, methods etc. 585 | No long functions, comments explaining unusual code, bug fixes, 587 | code assumptions 588 | Code assumptions are verified using asserts, code flows naturally – no deep nesting of 590 | conditionals or methods 591 |
defensive codingDoesn’t understand the 597 | concept 598 | Checks all arguments and asserts critical assumptions in codeMakes sure to check return 601 | values and check for exceptions around code that can fail. 602 | Has his own library to help with defensive coding, 604 | writes unit tests that simulate faults 605 |
error handlingOnly codes the happy 611 | case 612 | Basic error handling around code that can throw exceptions/generate errorsEnsures that 615 | error/exceptions leave program in good state, resources, connections and memory is all cleaned up 616 | properly 617 | Codes to detect possible exception before, maintain consistent exception handling strategy in all 619 | layers of code, come up with guidelines on exception handling for entire system. 620 |
IDEMostly uses IDE for text editingKnows their way around the interface, 627 | able to effectively use the IDE using menus. 628 | Knows keyboard shortcuts for most used operations.Has 631 | written custom macros 632 |
APINeeds to look up the documentation 638 | frequently 639 | Has the most frequently used APIs in memoryVast and In-depth knowledge of the 642 | API 643 | Has written libraries that sit on top of the API to simplify frequently used tasks and to fill in gaps 645 | in the API 646 | E.g. of API can be Java library, .net framework or the custom API for the 648 | application 649 |
frameworksHas not used any framework outside of the core platformHas 655 | heard about but not used the popular frameworks available for the platform. 656 | Has used more than one framework 658 | in a professional capacity and is well-versed with the idioms of the frameworks. 659 | Author of 661 | framework 662 |
requirementsTakes the given requirements and codes to specCome 669 | up with questions regarding missed cases in the spec 670 | Understand complete picture and come up with entire 672 | areas that need to be speced 673 | Able to suggest better alternatives and flows to given requirements based on 675 | experience 676 |
scriptingNo knowledge of scripting toolsBatch files/shell 683 | scripts 684 | Perl/Python/Ruby/VBScript/PowershellHas written and published reusable 687 | code 688 |
databaseThinks that Excel is a databaseKnows basic database 695 | concepts, normalization, ACID, transactions and can write simple selects 696 | Able to design good and normalized 698 | database schemas keeping in mind the queries that’ll have to be run, proficient in use of views, stored 699 | procedures, 700 | triggers and user defined types. Knows difference between clustered and non-clustered indexes. Proficient in use 701 | of 702 | ORM tools. 703 | Can do basic database administration, performance optimization, index optimization, write 705 | advanced select queries, able to replace cursor usage with relational sql, understands how data is stored 706 | internally, 707 | understands how indexes are stored internally, understands how databases can be mirrored, replicated etc. 708 | Understands how the two phase commit works. 709 |

Experience

2n (Level 0)n2 (Level 1)n (Level 2)log(n) 729 | (Level 3) 730 | Comments
languages with professional experienceImperative or Object 736 | Oriented 737 | Imperative, Object-Oriented and declarative (SQL), added bonus if they understand static vs dynamic 739 | typing, weak vs strong typing and static inferred types 740 | Functional, added bonus if they understand lazy 742 | evaluation, currying, continuations 743 | Concurrent (Erlang, Oz) and Logic (Prolog) 745 |
platforms with professional 750 | experience 751 | 12-34-56+
years of professional 760 | experience 761 | 12-56-910+
domain knowledgeNo 771 | knowledge of the domain 772 | Has worked on at least one product in the domain.Has worked on multiple 775 | products in the same domain. 776 | Domain expert. Has designed and implemented several products/solutions in the 778 | domain. Well versed with standard terms, protocols used in the domain. 779 |

Knowledge

tool 794 | knowledge 795 | Limited to primary IDE (VS.Net, Eclipse etc.)Knows about some alternatives to popular and 798 | standard tools. 799 | Good knowledge of editors, debuggers, IDEs, open source alternatives etc. etc. For e.g. 801 | someone who knows most of the tools from Scott Hanselman’s power tools list. Has used ORM tools. 802 | Has 804 | actually written tools and scripts, added bonus if they’ve been published. 805 |
languages 810 | exposed to 811 | Imperative or Object OrientedImperative, Object-Oriented and declarative (SQL), added 814 | bonus if they understand static vs dynamic typing, weak vs strong typing and static inferred 815 | types 816 | Functional, added bonus if they understand lazy evaluation, currying, continuationsConcurrent 819 | (Erlang, Oz) and Logic (Prolog) 820 |
codebase knowledgeHas never looked at the 826 | codebase 827 | Basic knowledge of the code layout and how to build the systemGood working knowledge of 830 | code base, has implemented several bug fixes and maybe some small features. 831 | Has implemented multiple big 833 | features in the codebase and can easily visualize the changes required for most features or bug fixes. 834 |
knowledge of upcoming technologiesHas not heard of the upcoming 840 | technologies 841 | Has heard of upcoming technologies in the fieldHas downloaded the alpha 844 | preview/CTP/beta and read some articles/manuals 845 | Has played with the previews and has actually built 847 | something with it and as a bonus shared that with everyone else 848 |
platform 853 | internals 854 | Zero knowledge of platform internalsHas basic knowledge of how the platform works 857 | internally 858 | Deep knowledge of platform internals and can visualize how the platform takes the program and 860 | converts it into executable code. 861 | Has written tools to enhance or provide information on platform internals. 863 | For e.g. disassemblers, decompilers, debuggers etc. 864 |
booksUnleashed series, 21 870 | days series, 24 hour series, dummies series… 871 | Code Complete, Don’t Make me Think, Mastering Regular 873 | Expressions 874 | Design Patterns, Peopleware, Programming Pearls, Algorithm Design Manual, Pragmatic Programmer, 876 | Mythical Man month 877 | Structure and Interpretation of Computer Programs, Concepts Techniques, Models of 879 | Computer Programming, Art of Computer Programming, Database systems , by C. J Date, Thinking Forth, Little 880 | Schemer 881 |
blogsHas heard of them but never got the time.Reads 888 | tech/programming/software engineering blogs and listens to podcasts regularly. 889 | Maintains a link blog with 891 | some collection of useful articles and tools that he/she has collected 892 | Maintains a blog in which personal 894 | insights and thoughts on programming are shared 895 |
900 |

901 |
902 | 903 | 904 | 905 | 906 | 907 | -------------------------------------------------------------------------------- /README.ru.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

12 |
13 | 14 | 15 | Bot logo 16 | 17 | # Матрица компетентности программиста 18 | 19 |
20 | 21 | Прочитать версию на другом языке: [English](README.md) 22 | 23 | ## Всем привет. 24 | 25 | Сегодня 13 марта 2023 года, и так уж получилось что более 3 лет я активно изучаю программирование на питоне, а так 26 | же науку о данных. Через половину года заканчивается контракт и я решил - пришло время смены деятельности из 27 | радиоинженера в специалиста машинного обучения. Но как оценить себя, как показать будущему работодателю, что я знаю, 28 | умею, как развиваюсь??? Разделяй и властвуй (лат. divide et impera) - гласит максима римского сената, подойдем 29 | системно к ответу на заданный вопрос. Разделим все составляющие моих знаний специалиста и оценим их используя 30 | матрицу компетентности. 31 | 32 | Разумеется я не стал изобретать велосипед и взял уже готовую матрицу (наиболее распространенный вариант предложен 33 | Сидзин Джозефом [вот](https://sijinjoseph.netlify.app/programmer-competency-matrix/)) и честно отвечал на указанные 34 | вопросы, ответ старательно складывал в отдельные файлы. 35 | 36 | 37 | #### В процессе... 38 | 39 | 40 |
41 | Знания данных, алгоритмы, ПО 42 | 43 | - [ ] **Структуры данных** 44 | - [x] [Уровень 0](00.Структуры_данных.md#Разница-между-массивом-и-связным-списком) - Не знает разницы между массивом и связанным списком 45 | - [x] [Уровень 1](00.Структуры_данных.md#Применение-различных-структур-данных-python-в-различных-алгоритмах) - Способность объяснять и 46 | использовать массивы, связанные списки, словари и т. д. в практических задачах программирования 47 | - [x] [Уровень 2](00.Структуры_данных.md#Плюсы-и-минусы-использования-базовых-структур-данных-Python) - Понимает плюсы и минусы 48 | использования тех или иных базовых структур данных (размер памяти, 49 | время выполнения операций с данными, в чем разница между массивами и связными списками в этом плане). 50 | Может объяснить как реализовать хэш-таблицы и как обработать коллизии. Приоритетные очереди и способы их 51 | реализации и т. д. 52 | - [x] [Уровень 3](00.Структуры_данных.md#Знание-расширенных-структур-данных) - Знание сложных структур данных, таких как B-дерево, 53 | Биномиальная куча и куча Фибоначчи, АВЛ-дерево, Красно-чёрное дерево, Косое дерево, Список с пропусками, 54 | TRIE-структуры и т.д. 55 | 56 | - [ ] **Алгоритмы** 57 | - [x] Уровень 0 - Невозможно найти среднее число чисел в массиве (Сложно поверить, но я проводил собеседования с такими кандидатами) 58 | - [x] Уровень 1 - Базовые алгоритмы сортировки, поиска и обхода структуры данных и извлечения 59 | - [x] Уровень 2 - Дерево, График, простые жадные алгоритмы и алгоритмы "разделяй и властвуй", способен понимать 60 | актуальность уровней этой матрицы. 61 | - [ ] Уровень 3 - Способность распознавать и кодировать решения динамического программирования, хорошее знание графовых алгоритмов, 62 | хорошее знание алгоритмов численных вычислений, способность идентифицировать проблемы NP и т. д. 63 | 64 | - [ ] **Системное программирование** 65 | - [x] Уровень 0 - Не знает, что такое компилятор, компоновщик или интерпретатор 66 | - [x] Уровень 1 - Базовое понимание компиляторов, компоновщиков и интерпретаторов. Понимает, что такое ассемблерный код и 67 | как все работает на аппаратном уровне. Некоторые знания о виртуальной памяти и подкачке. 68 | - [ ] Уровень 2 — понимание режима ядра и пользовательского режима, многопоточности, примитивов синхронизации и того, как они работают. 69 | реализован, способен читать ассемблерный код. Понимает, как работают сети, понимает сетевые протоколы и 70 | программирование на уровне сокетов. 71 | - [ ] Уровень 3 - Понимает весь программный стек, оборудование (ЦП + Память + Кэш + 72 | прерывания + микрокод), бинарный код, сборка, статическая и динамическая компоновка, компиляция, интерпретация, JIT 73 | компиляция, сборка мусора, куча, стек, адресация памяти... 74 | 75 |
76 | 77 | 78 | -------------------------------------------------------------------------------- /art/AVLtreef.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BEPb/Programmer_Competency_Matrix/d4310d9b717cee80f7adda0d1a71872638a70c17/art/AVLtreef.svg.png -------------------------------------------------------------------------------- /art/Red-black_tree_example_with_NIL.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BEPb/Programmer_Competency_Matrix/d4310d9b717cee80f7adda0d1a71872638a70c17/art/Red-black_tree_example_with_NIL.svg.png -------------------------------------------------------------------------------- /art/binom_ex_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BEPb/Programmer_Competency_Matrix/d4310d9b717cee80f7adda0d1a71872638a70c17/art/binom_ex_1.jpg -------------------------------------------------------------------------------- /art/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BEPb/Programmer_Competency_Matrix/d4310d9b717cee80f7adda0d1a71872638a70c17/art/logo.png --------------------------------------------------------------------------------