[{"data":1,"prerenderedAt":832},["ShallowReactive",2],{"navigation":3,"/blog/python/st31":378,"/blog/python/st31-surround":827},[4],{"title":5,"path":6,"stem":7,"children":8,"page":114},"Blog","/blog","blog",[9,115,184,321],{"title":10,"path":11,"stem":12,"children":13,"page":114},"Ege","/blog/ege","blog/ege",[14,18,22,26,30,34,38,42,46,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110],{"title":15,"path":16,"stem":17},"ЕГЭ Задание 1","/blog/ege/task1","blog/ege/task1",{"title":19,"path":20,"stem":21},"ЕГЭ Задание 10","/blog/ege/task10","blog/ege/task10",{"title":23,"path":24,"stem":25},"ЕГЭ Задание 11","/blog/ege/task11","blog/ege/task11",{"title":27,"path":28,"stem":29},"ЕГЭ Задание 12","/blog/ege/task12","blog/ege/task12",{"title":31,"path":32,"stem":33},"ЕГЭ Задание 13","/blog/ege/task13","blog/ege/task13",{"title":35,"path":36,"stem":37},"ЕГЭ Задание 14","/blog/ege/task14","blog/ege/task14",{"title":39,"path":40,"stem":41},"ЕГЭ Задание 15","/blog/ege/task15","blog/ege/task15",{"title":43,"path":44,"stem":45},"ЕГЭ Задание 16","/blog/ege/task16","blog/ege/task16",{"title":47,"path":48,"stem":49},"ЕГЭ Задание 17","/blog/ege/task17","blog/ege/task17",{"title":51,"path":52,"stem":53},"ЕГЭ Задание 18","/blog/ege/task18","blog/ege/task18",{"title":55,"path":56,"stem":57},"ЕГЭ Задание 19, 20, 21","/blog/ege/task19_20_21","blog/ege/task19_20_21",{"title":59,"path":60,"stem":61},"ЕГЭ Задание 2","/blog/ege/task2","blog/ege/task2",{"title":63,"path":64,"stem":65},"ЕГЭ Задание 22","/blog/ege/task22","blog/ege/task22",{"title":67,"path":68,"stem":69},"ЕГЭ Задание 23","/blog/ege/task23","blog/ege/task23",{"title":71,"path":72,"stem":73},"ЕГЭ Задание 24","/blog/ege/task24","blog/ege/task24",{"title":75,"path":76,"stem":77},"ЕГЭ Задание 25","/blog/ege/task25","blog/ege/task25",{"title":79,"path":80,"stem":81},"ЕГЭ Задание 26","/blog/ege/task26","blog/ege/task26",{"title":83,"path":84,"stem":85},"ЕГЭ Задание 27","/blog/ege/task27","blog/ege/task27",{"title":87,"path":88,"stem":89},"ЕГЭ Задание 3","/blog/ege/task3","blog/ege/task3",{"title":91,"path":92,"stem":93},"ЕГЭ Задание 4","/blog/ege/task4","blog/ege/task4",{"title":95,"path":96,"stem":97},"ЕГЭ Задание 5","/blog/ege/task5","blog/ege/task5",{"title":99,"path":100,"stem":101},"ЕГЭ Задание 6","/blog/ege/task6","blog/ege/task6",{"title":103,"path":104,"stem":105},"ЕГЭ Задание 7","/blog/ege/task7","blog/ege/task7",{"title":107,"path":108,"stem":109},"ЕГЭ Задание 8","/blog/ege/task8","blog/ege/task8",{"title":111,"path":112,"stem":113},"ЕГЭ Задание 9","/blog/ege/task9","blog/ege/task9",false,{"title":116,"path":117,"stem":118,"children":119,"page":114},"Oge","/blog/oge","blog/oge",[120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180],{"title":121,"path":122,"stem":123},"ОГЭ Задание 1","/blog/oge/task1","blog/oge/task1",{"title":125,"path":126,"stem":127},"ОГЭ Задание 10","/blog/oge/task10","blog/oge/task10",{"title":129,"path":130,"stem":131},"ОГЭ Задание 11","/blog/oge/task11","blog/oge/task11",{"title":133,"path":134,"stem":135},"ОГЭ Задание 12","/blog/oge/task12","blog/oge/task12",{"title":137,"path":138,"stem":139},"ОГЭ Задание 13","/blog/oge/task13","blog/oge/task13",{"title":141,"path":142,"stem":143},"ОГЭ Задание 14","/blog/oge/task14","blog/oge/task14",{"title":145,"path":146,"stem":147},"ОГЭ Задание 15","/blog/oge/task15","blog/oge/task15",{"title":149,"path":150,"stem":151},"ОГЭ Задание 16","/blog/oge/task16","blog/oge/task16",{"title":153,"path":154,"stem":155},"ОГЭ Задание 2","/blog/oge/task2","blog/oge/task2",{"title":157,"path":158,"stem":159},"ОГЭ Задание 3","/blog/oge/task3","blog/oge/task3",{"title":161,"path":162,"stem":163},"ОГЭ Задание 4","/blog/oge/task4","blog/oge/task4",{"title":165,"path":166,"stem":167},"ОГЭ Задание 5","/blog/oge/task5","blog/oge/task5",{"title":169,"path":170,"stem":171},"ОГЭ Задание 6","/blog/oge/task6","blog/oge/task6",{"title":173,"path":174,"stem":175},"ОГЭ Задание 7","/blog/oge/task7","blog/oge/task7",{"title":177,"path":178,"stem":179},"ОГЭ Задание 8","/blog/oge/task8","blog/oge/task8",{"title":181,"path":182,"stem":183},"ОГЭ Задание 9","/blog/oge/task9","blog/oge/task9",{"title":185,"path":186,"stem":187,"children":188,"page":114},"Python","/blog/python","blog/python",[189,193,197,201,205,209,213,217,221,225,229,233,237,241,245,249,253,257,261,265,269,273,277,281,285,289,293,297,301,305,309,313,317],{"title":190,"path":191,"stem":192},"Знакомство с синтаксисом","/blog/python/st1","blog/python/st1",{"title":194,"path":195,"stem":196},"Отладка","/blog/python/st10","blog/python/st10",{"title":198,"path":199,"stem":200},"Модули и пакеты","/blog/python/st11","blog/python/st11",{"title":202,"path":203,"stem":204},"Кортежи","/blog/python/st12","blog/python/st12",{"title":206,"path":207,"stem":208},"Знакомство со списками","/blog/python/st13","blog/python/st13",{"title":210,"path":211,"stem":212},"Списки и циклы","/blog/python/st14","blog/python/st14",{"title":214,"path":215,"stem":216},"Использование списков ч.1","/blog/python/st15","blog/python/st15",{"title":218,"path":219,"stem":220},"Использование списков ч.2","/blog/python/st16","blog/python/st16",{"title":222,"path":223,"stem":224},"Использование списков ч.3","/blog/python/st17","blog/python/st17",{"title":226,"path":227,"stem":228},"Словари","/blog/python/st18","blog/python/st18",{"title":230,"path":231,"stem":232},"Множества","/blog/python/st19","blog/python/st19",{"title":234,"path":235,"stem":236},"Переменные","/blog/python/st2","blog/python/st2",{"title":238,"path":239,"stem":240},"Хеш-таблицы","/blog/python/st20","blog/python/st20",{"title":242,"path":243,"stem":244},"Решето Эратосфена","/blog/python/st21","blog/python/st21",{"title":246,"path":247,"stem":248},"Длинная арифметика","/blog/python/st22","blog/python/st22",{"title":250,"path":251,"stem":252},"Декораторы функций","/blog/python/st23","blog/python/st23",{"title":254,"path":255,"stem":256},"Знакомство с алгоритмами","/blog/python/st24","blog/python/st24",{"title":258,"path":259,"stem":260},"Бинарный поиск – примеры задач","/blog/python/st25","blog/python/st25",{"title":262,"path":263,"stem":264},"Сортировка выбором","/blog/python/st26","blog/python/st26",{"title":266,"path":267,"stem":268},"Рекурсия и стек","/blog/python/st27","blog/python/st27",{"title":270,"path":271,"stem":272},"Быстрая сортировка","/blog/python/st28","blog/python/st28",{"title":274,"path":275,"stem":276},"Поиск в ширину","/blog/python/st29","blog/python/st29",{"title":278,"path":279,"stem":280},"Работа со строками","/blog/python/st3","blog/python/st3",{"title":282,"path":283,"stem":284},"Поиск в глубину","/blog/python/st30","blog/python/st30",{"title":286,"path":287,"stem":288},"Сбалансированные деревья","/blog/python/st31","blog/python/st31",{"title":290,"path":291,"stem":292},"Алгоритм Дейкстры","/blog/python/st32","blog/python/st32",{"title":294,"path":295,"stem":296},"Жадные алгоритмы","/blog/python/st33","blog/python/st33",{"title":298,"path":299,"stem":300},"Типы данных","/blog/python/st4","blog/python/st4",{"title":302,"path":303,"stem":304},"О функциях","/blog/python/st5","blog/python/st5",{"title":306,"path":307,"stem":308},"Свойства и методы","/blog/python/st6","blog/python/st6",{"title":310,"path":311,"stem":312},"Определение функций","/blog/python/st7","blog/python/st7",{"title":314,"path":315,"stem":316},"Логика","/blog/python/st8","blog/python/st8",{"title":318,"path":319,"stem":320},"Циклы","/blog/python/st9","blog/python/st9",{"title":322,"path":323,"stem":324,"children":325,"page":114},"Toi","/blog/toi","blog/toi",[326,330,334,338,342,346,350,354,358,362,366,370,374],{"title":327,"path":328,"stem":329},"Информация и информационные процессы","/blog/toi/st1","blog/toi/st1",{"title":331,"path":332,"stem":333},"Электронные таблицы","/blog/toi/st10","blog/toi/st10",{"title":335,"path":336,"stem":337},"Система, её свойства и компоненты. Моделирование","/blog/toi/st11","blog/toi/st11",{"title":339,"path":340,"stem":341},"Представление информации в компьютере","/blog/toi/st12","blog/toi/st12",{"title":343,"path":344,"stem":345},"Средства информационно-коммуникационных технологий. Файловая система","/blog/toi/st13","blog/toi/st13",{"title":347,"path":348,"stem":349},"Комбинаторика","/blog/toi/st2","blog/toi/st2",{"title":351,"path":352,"stem":353},"Адресация в интернете","/blog/toi/st3","blog/toi/st3",{"title":355,"path":356,"stem":357},"Измерение количества информации","/blog/toi/st4","blog/toi/st4",{"title":359,"path":360,"stem":361},"Системы счисления","/blog/toi/st5","blog/toi/st5",{"title":363,"path":364,"stem":365},"Диаграммы Эйлера — Венна","/blog/toi/st6","blog/toi/st6",{"title":367,"path":368,"stem":369},"Условие Фано","/blog/toi/st7","blog/toi/st7",{"title":371,"path":372,"stem":373},"Теория графов","/blog/toi/st8","blog/toi/st8",{"title":375,"path":376,"stem":377},"Алгебра логики","/blog/toi/st9","blog/toi/st9",{"id":379,"title":286,"author":380,"body":385,"date":817,"description":818,"extension":819,"image":820,"meta":821,"minRead":822,"navigation":823,"num":824,"path":287,"seo":825,"stem":288,"__hash__":826},"python/blog/python/st31.md",{"name":381,"avatar":382},"Штана Альберт Игоревич",{"src":383,"alt":384},"me.jpg","@ashtana",{"type":386,"value":387,"toc":797},"minimark",[388,392,397,413,416,421,442,447,450,457,464,467,470,482,491,508,512,521,526,529,535,538,543,546,551,554,559,562,567,570,575,578,582,589,595,598,601,606,609,614,617,622,625,630,633,641,644,693,697,716,720,723,729,732,742,745,749,756,759,762,765,768,773,776,779,790,793],[389,390,286],"h2",{"id":391},"сбалансированные-деревья",[393,394],"card-collapsible",{":isList":395,"title":396},"[\"Узнаете о структуре данных, называемой бинарным деревом поиска (BST, Binary Search Tree).\",\"Разберётесь почему сбалансированные деревья часто бывают эффективнее массивов и связанных списков.\",\"Узнаете о АВЛ-деревьях — разновидности сбалансированного дерева BST.\"]","Из этой статьи вы",[398,399,400],"blockquote",{},[401,402,403,404,408,409,412],"p",{},"В предыдущих статьях были рассмотрены два подхода и алгоритмы для поиска по деревьям: ",[405,406,407],"a",{"href":275},"поиск в ширину"," и ",[405,410,411],{"href":283},"поиск в глубину",".\nЗдесь далее текст пойдёт о сбалансированных деревьях.",[401,414,415],{},"Если связанные списки и массивы не дают нужной производительности, целесообразно обратиться к структуре графов.\nРассмотрим, какой производительности можно добиться с помощью деревьев.\nОтличную производительность могут обеспечивать так называемые сбалансированные деревья.",[417,418,420],"h3",{"id":419},"балансировка","Балансировка",[401,422,423,424,428,429,432,433,435,436,438,439,441],{},"Помните бинарный поиск?\nС его помощью можно найти информацию намного быстрее, чем простым поиском — со сложностью ",[425,426,427],"em",{},"O(log n)"," вместо ",[425,430,431],{},"O(n)",".\nНо, есть одна проблема: вставка.\nКонечно, поиск занимает время ",[425,434,427],{},", но массив должен быть отсортирован.\nЕсли требуется вставить новое число в отсортированный массив, это займёт время ",[425,437,431],{},".\nПроблема здесь в том, чтобы найти место для нового значения.\nПридётся передвинуть несколько элементов, чтобы освободить для него место.\nВот если бы вставку можно было выполнить как в связанном списке, где достаточно поменять пару указателей...\nНо минус связанного списка в том, что поиск выполняется за линейное время ",[425,440,431],{},".\nКак взять и использовать только лучшие стороны обоих решений из массивов и связанных списков?",[443,444,446],"h4",{"id":445},"скорость-вставки-в-деревьях","Скорость вставки в деревьях",[401,448,449],{},"Нам понадобится структура данных объединяющая идеи вставки и поиска.\nЭта структура называется сбалансированное бинарное дерево поиска (BST).\nBST это разновидность бинарного дерева. Рассмотрим пример:",[401,451,452],{},[453,454],"img",{"alt":455,"src":456},"Пример дерева","/images/blog/python/st31/img_1.png",[401,458,459,460,463],{},"Как и в бинарном дереве, каждый узел имеет до двух дочерних узлов: левый и правый.\nНо у этого дерева есть одно свойство, относящее его к BST: ",[425,461,462],{},"значение левого дочернего узла всегда меньше, чем значение узла, а значение правого дочернего узла всегда больше.","\nТаким образом, для корневого узла 10 левый дочерний узел имеет меньшее значение 4, а правый дочерний узел — большее значение 15.\nК тому же, все числа в поддереве левого дочернего узла меньше самого узла!\nЭто особое свойство означает, что поиск будет выполняться очень быстро.",[401,465,466],{},"Давайте посмотрим на алгоритм, содержится ли число 6 в этом дереве? Начнём с корневого узла.\nЧисло 6 меньше 10, поэтому проверяем левое поддерево.\nПомните: все узлы с меньшими значениями находятся в левом поддереве, а все узлы с большими значениями — в правом.\nСледовательно, мы сразу понимаем, что проверять узлы справа не нужно, потому что 6 там не будет.\nОпускаясь по левому поддереву от 10, переходим к узлу 4.\nЧисло 6 больше 4, поэтому далее идём направо.\nИ вот мы нашли число 6. Теперь поищем другое число — 8. Поиск происходит аналогично по такому же пути.",[401,468,469],{},"Собственно, все рассуждения о деревьях обусловлены одной необходимостью: знать, работают ли они быстрее массивов и связанных списков.\nРассмотрим производительность деревьев, но для этого необходимо учитывать их высоту. Короткие деревья работают быстрее.\nВ лучшем случае высота дерева равна 2. Это означает, что к любому узлу можно перейти от корневого узла максимум за 2 шага.\nВысота дерева для худшего случая с теми же данными будет равна 6.\nЭто означает, что к любому узлу можно перейти от корневого узла максимум за 6 шагов.\nПомните игру с отгадыванием чисел?\nЧтобы угадать число из набора 100 чисел, бинарный поиск потребует максимум 7 попыток, а простому может потребоваться все 100 попыток.\nНечто похожее происходит и с деревьями.",[401,471,472,473,475,476,479,480],{},"Дерево для худшего случая содержит больше уровней и у него хуже с производительностью.\nВ нём все узлы выстроены в одну линию. Дерево имеет высоту ",[425,474,431],{},", так что поиск будет выполняться за время ",[425,477,478],{},"O(n).","\nПредставить можно так: дерево напоминает связанный список, так как один узел содержит ссылку на другой.\nПоиск по связанному списку выполняется за время ",[425,481,478],{},[401,483,484,485,487,488,490],{},"Дерево для худшего случая имеет высоту ",[425,486,427],{},", а поиск по нему занимает время ",[425,489,427],{},".",[401,492,493,494,497,498,500,501,503,504,507],{},"Таким образом, ситуация очень похожа на сравнение бинарного поиска с простым линейным поиском!\nЕсли высота дерева всегда будет обеспечиваться как ",[425,495,496],{},"log n",", то поиск будет выполнятся за время ",[425,499,427],{},".\nНо как добиться, чтобы высота составляла ",[425,502,427],{},"? Кратчайшее время для BST может составлять ",[425,505,506],{},"O(log n).","\nЧтобы этого добиться, нужно сбалансировать дерево. Рассмотрим сбалансированное дерево BST.",[443,509,511],{"id":510},"авл-деревья","АВЛ-деревья",[401,513,514,515,517,518,520],{},"АВЛ-деревья (АВЛ аббревиатура образована от фамилий ученых придумавших эту структуру данных: Адельсон, Вельский, Ландис)\nсоставляют разновидность \"самобалансируемых\" BST.\nЭто означает, что АВЛ-деревья сохраняют высоту ",[425,516,427],{},".\nКаждый раз, когда дерево \"разбалансируется\", то есть его высота становится отличной от O(log n), оно корректирует себя.\nАВЛ-дерево обеспечивает нужную высоту ",[425,519,427],{}," за счёт самобалансировки и поворотов.",[522,523,525],"h5",{"id":524},"повороты-авл-дерева","Повороты АВЛ-дерева",[401,527,528],{},"Повороты — популярный метод балансировки деревьев. Представьте, что имеется дерево с тремя узлами.\nЛюбой из них может быть корневым. В результате поворота набор узлов смещается, образуя новую конфигурацию.\nНачнем с двух узлов, рассмотрим поворот:",[401,530,531],{},[453,532],{"alt":533,"src":534},"Пример АВЛ-дерева","/images/blog/python/st31/img_2.png",[401,536,537],{},"Высоты дочерних узлов неодинаковы: разность между ними не превышает 1.\nОднако разность в 1 уровень приемлема для АВЛ-деревьев. Теперь добавим ещё один узел.",[401,539,540],{},[453,541],{"alt":533,"src":542},"/images/blog/python/st31/img_3.png",[401,544,545],{},"Дерево \"разбалансировалось\". Нужно его повернуть.",[401,547,548],{},[453,549],{"alt":533,"src":550},"/images/blog/python/st31/img_4.png",[401,552,553],{},"Выполнили поворот влево, теперь дерево снова сбалансировано.\nДобавим ещё один узел.",[401,555,556],{},[453,557],{"alt":533,"src":558},"/images/blog/python/st31/img_5.png",[401,560,561],{},"И ещё один.",[401,563,564],{},[453,565],{"alt":533,"src":566},"/images/blog/python/st31/img_6.png",[401,568,569],{},"Снова выполним поворот.",[401,571,572],{},[453,573],{"alt":533,"src":574},"/images/blog/python/st31/img_7.png",[401,576,577],{},"После поворота АВЛ-деревья перебалансируются.\nЗаметим, что в последнем повороте вместо узла 15 поворачивался узел 30. Разберёмся далее почему так.",[522,579,581],{"id":580},"как-авл-дерево-узнает-что-требуется-поворот","Как АВЛ-дерево узнает, что требуется поворот?",[401,583,584,585,588],{},"Чтобы дерево знало, когда требуется самобалансировка, оно должно хранить дополнительную информацию.\nВ каждом узле хранится один или два вида информации: значение высоты или значение, которое иногда называют ",[425,586,587],{},"коэффициентом балансировки",".\nЭтот коэффициент должен быть равен -1, 0 или 1.",[401,590,591],{},[453,592],{"alt":593,"src":594},"Пример АВЛ-деревьев","/images/blog/python/st31/img_8.png",[401,596,597],{},"Выше на рисунке приведены коэффициенты балансировки только для корневых узлов, но может понадобиться хранить коэффициент балансировки для каждого узла.",[401,599,600],{},"Коэффициент балансировки сообщает, какой дочерний узел выше и насколько.\nПо коэффициенту балансировки дерево может определить, когда следует проводить перебалансировку.\nЗначение 0 означает, что дерево сбалансировано.\nСо значениями -1 или 1 все нормально, потому что, АВЛ-деревья не обязаны быть идеально сбалансированы: разность 1 допустима.\nНо если коэффициент балансировки падает ниже -1 или поднимается выше 1, дерево нуждается в перебалансировке.\nНиже пример двух таких деревьев:",[401,602,603],{},[453,604],{"alt":593,"src":605},"/images/blog/python/st31/img_9.png",[401,607,608],{},"В каждом узле должна храниться либо высота, либо коэффициент балансировки. Можно хранить и то и другое.\nЕсли известны высоты каждого поддерева, то легко вычисляется коэффициент балансировки.\nРассмотрим пример:",[401,610,611],{},[453,612],{"alt":533,"src":613},"/images/blog/python/st31/img_10.png",[401,615,616],{},"Для начала запишем высоту и коэффициент балансировки для каждого узла.\nНа этой схеме В – высота, а К – коэффициент балансировки.\nХраним в данном примере два значения, но достаточно в реализации хранить только одно.\nУ всех корневых узлов коэффициент балансировки равен 0: у них нет дочерних узлов, поэтому и поддерживать баланс не нужно.\nДобавим в дерево новый узел:",[401,618,619],{},[453,620],{"alt":533,"src":621},"/images/blog/python/st31/img_11.png",[401,623,624],{},"После того как узел был добавлен, необходимо задать для него высоту и коэффициент балансировки.\nЗатем следует подняться вверх по дереву, обновляя высоты и коэффициенты балансировки для всех его предков.\nПосле вставки нового элемента в дерево — обновляются все коэффициенты балансировки для предков вставленного узла.\nАВЛ-дерево проверяет коэффициент балансировки, чтобы после выполнять перебалансировку.\nВ данном примере выше присутствует коэффициент балансировки -2, это означает что узел в дереве нужно повернуть!\nПовернём узел 10:",[401,626,627],{},[453,628],{"alt":533,"src":629},"/images/blog/python/st31/img_12.png",[401,631,632],{},"Теперь дерево сбалансировано. Если продолжить движение вверх по дереву то также ничего балансировать уже будет не нужно.\nДвигаться от \"перебалансированного\" узла вверх по дереву необязательно, потому что АВЛ-деревья требуют не более одной \"перебалансировки\".",[401,634,635,636,638,639,490],{},"Итак, АВЛ-деревья хороши, если требуется сбалансированное дерево BST. АВЛ-деревья обеспечивают производительность поиска ",[425,637,427],{},".\nА что со вставкой? Вставка сводится к поиску места для вставки узла и добавления указателя, как в связанном списке.\nНапример, если необходимо вставить элемент в сбалансированное АВЛ-дерево, то необходимо сначала определить, где добавить указатель.\nИ таким образом, вставка тоже выполняется за время ",[425,640,427],{},[401,642,643],{},"Получается что структура данных АВЛ-дерево или сбалансированное дерево BST обеспечивает и быструю вставку и быстрый поиск!\nОбщая информация по трём структурам данных в таблице ниже:",[645,646,647,666],"table",{},[648,649,650],"thead",{},[651,652,653,657,660,663],"tr",{},[654,655,656],"th",{},"-------",[654,658,659],{},"Отсортированный массив",[654,661,662],{},"Связанный список",[654,664,665],{},"АВЛ-дерево",[667,668,669,681],"tbody",{},[651,670,671,675,677,679],{},[672,673,674],"td",{},"Поиск",[672,676,427],{},[672,678,431],{},[672,680,427],{},[651,682,683,686,688,691],{},[672,684,685],{},"Вставка",[672,687,431],{},[672,689,690],{},"O(1)",[672,692,427],{},[443,694,696],{"id":695},"косые-деревья","Косые деревья",[401,698,699,700,702,703,706,707,709,710,712,713,715],{},"Косые деревья или Splay-деревья представляют другой подход к сбалансированным деревьям BST.\nИх самое лучшее свойство в том, что если был произведён недавно поиск какого-то элемента, то следующий поиск будет быстрее.\nЭто свойство интуитивно рассматривается положительно.\nПредставьте, что необходимо реализовать работу с программой, которая получает почтовый индекс и находит по нему город.\nИ также представьте, что необходимо многократно каждый раз получать и проводить поиск одного и того же почтового индекса.\nПочему бы не запомнить прошлый результат поиска? Косые деревья позволяют это сделать.\nКогда происходит поиск в косом дереве, он становится после нахождения новым корневым узлом.\nТак при повторном поиске этот же узел будет найден сразу же!\nВ общем случае узлы, которые недавно искали, группируются ближе к корню и находятся быстрее.\nС другой стороны, дерево заведомо не будет сбалансировано, а значит, некоторые операции поиска будут занимать время, большее чем ",[425,701,427],{},", и даже достигать линейного времени!\nКроме того, может потребоваться повернуть узел до корневой позиции, если он ещё некорневой,а это тоже потребует времени.\nНо в целом рассматривая реализацию конкретной задачи, нас должно устраивать, что дерево не будет сбалансировано постоянно.\nГлавное, что при проведении n операций поиска общее время ",[425,704,705],{},"O(n log n)"," гарантированно — т.е. ",[425,708,427],{}," на один поиск.\nТаким образом, хотя один поиск может занять время, превышающее ",[425,711,427],{},", в среднем все операции поиска сходятся ко времени ",[425,714,427],{},", а цель как раз и есть ускорение поиска.",[443,717,719],{"id":718},"b-деревья","B-деревья",[401,721,722],{},"B-деревья представляют собой обобщённую форму бинарных деревьев.\nОни часто используются для построения баз данных.\nНиже представлен пример B-дерева:",[401,724,725],{},[453,726],{"alt":727,"src":728},"Пример В-дерева","/images/blog/python/st31/img_13.png",[401,730,731],{},"Выглядит интересно, правда? Можно заметить, что некоторые узлы имеют более двух дочерних узлов.\nВ отличие от других деревьев поиска (например, двоичного дерева, АВЛ‑дерева),\nгде каждый узел хранит один ключ и максимум двух потомков, в B‑дереве:",[733,734,735,739],"ul",{},[736,737,738],"li",{},"узел может содержать несколько ключей;",[736,740,741],{},"узел может иметь более двух потомков.",[401,743,744],{},"B-дерево — это обобщенная форма бинарного дерева поиска.",[522,746,748],{"id":747},"какие-преимущества-есть-у-b-деревьев","Какие преимущества есть у B-деревьев?",[401,750,751,752,755],{},"Для B-деревьев существует оптимизация, интересная тем, что применяется на физическом уровне.\nПри поиске по дереву получение данных требует перемещения механических компонентов оборудования (например, считывающей головки HDD диска).\nВремя получения данных называется ",[425,753,754],{},"временем поиска",". Оно может быть важным фактором, определяющим, насколько быстро или медленно работает алгоритм.",[401,757,758],{},"Ситуация можно сравнить с посещением магазина. Вы можете покупать продукты по одному. Представьте, что вы решаете купить яблоки.\nВернувшись из магазина, вы понимаете, что было бы неплохо купить ещё и апельсины, и возвращаетесь в магазин.\nПо возвращении вы видите, что у вас закончился шоколад, и снова поход в магазин... Это крайне неэффективно!\nНамного лучше зайти в магазин и купить за раз все необходимые товары, находясь в нём.\nВремя похода в магазин и возвращения из него представляет собой время поиска.",[401,760,761],{},"Фундаментальная концепция B-деревьев заключается в том, что после выполнения поиска можно прочитать дополнительные данные в память.\nЭто как сходить в магазин и купить сразу всё необходимое чтобы не ходить в него снова.",[401,763,764],{},"В B-деревьях используются большие узлы; каждый узел может иметь больше ключей и дочерних узлов, чем бинарное дерево.\nТаким образом, чтение каждого узла займёт больше времени.\nС другой стороны, поиск при больших данных ускоряется, потому что за один раз читается больший объём данных.\nИменно это обстоятельство обеспечивает высокую скорость работы с B-деревом.",[401,766,767],{},"Структура B-деревьев популярна в реализациях баз данных.\nИ это не удивительно, ведь в базах данных много времени занимает чтение с дисков.\nКак происходит обход B-дерева? Начинается всё с нижнего крайнего левого или правого узла.\nА дальше змейкой обход остальных узлов.",[401,769,770],{},[453,771],{"alt":727,"src":772},"/images/blog/python/st31/img_14.png",[401,774,775],{},"Обратите внимание на свойство как у BST деревьев. Для каждого ключа значения ключей в левом поддереве меньше, а значения ключей в правом поддереве — больше него.\nНапример, для ключа 6 левое поддерево состоит из ключей 4 и 5, а правое поддерево из ключей 7 и 8.\nТакже количество дочерних узлов на 1 больше количества ключей. Таким образом, корневой узел имеет один ключ и два дочерних узла.\nКаждый из дочерних узлов имеет два ключа и три дочерних узла.",[401,777,778],{},"На этом можно завершить изучение деревьев.\nВам вряд ли придётся реализовывать их самостоятельно, но важно знать, что деревья — это разновидность графов и они обладают отличной производительностью.",[398,780,781],{},[401,782,783,784,787,788,490],{},"В следующей статье можно узнать о популярном алгоритме на ",[425,785,786],{},"взвешенных графах",": ",[405,789,290],{"href":291},[443,791],{"id":792},"",[393,794],{":isList":795,"title":796},"[\"Сбалансированные бинарные деревья поиска (BST) обеспечивают такую же производительность в нотации \\\"О-большое\\\", как массивы, и лучшую производительность вставки;\",\"Высота дерева влияет на его производительность;\",\"АВЛ-деревья — популярная разновидность сбалансированных деревьев BST. Как и большинство сбалансированных деревьев, АВЛ-деревья балансируются поворотом;\",\"В-деревья представляют собой обобщенные деревья BST, у которых каждый узел может иметь несколько ключей и несколько дочерний узлов;\",\"Время поиска можно сравнить со временем похода в магазин. В-деревья минимизируют время поиска за счёт чтения большего объёма данных за одну операцию.\"]","ШПАРГАЛКА",{"title":792,"searchDepth":798,"depth":799,"links":800},2,5,[801],{"id":391,"depth":798,"text":286,"children":802},[803],{"id":419,"depth":804,"text":420,"children":805},3,[806,808,812,813,816],{"id":445,"depth":807,"text":446},4,{"id":510,"depth":807,"text":511,"children":809},[810,811],{"id":524,"depth":799,"text":525},{"id":580,"depth":799,"text":581},{"id":695,"depth":807,"text":696},{"id":718,"depth":807,"text":719,"children":814},[815],{"id":747,"depth":799,"text":748},{"id":792,"depth":807,"text":792},"2026-03-18T00:00:00.000Z","Бинарное дерево поиска. Сбалансированные деревья. АВЛ-деревья. B-деревья.","md","images/blog/python/st31/img.png",{},23,true,31,{"title":286,"description":818},"fxnQQ07zEg32tGEzbOj1N4oEug2oFVYX_C-5lu169hc",[828,830],{"title":282,"path":283,"stem":284,"description":829,"children":-1},"Алгоритмы с деревьями. Алгоритм поиска в глубину(DFS) на деревьях. Алгоритм Хаффмана.",{"title":290,"path":291,"stem":292,"description":831,"children":-1},"Взвешенные графы. Поиск кратчайшего пути.",1777359499040]