<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=138.197.160.42&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=138.197.160.42&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/138.197.160.42"/>
		<updated>2026-04-09T16:00:39Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%B2%D0%BE%D1%81%D1%82%D0%BE%D1%80%D0%BE%D0%BD%D0%BD%D0%B8%D0%B5_%D0%BA%D1%80%D0%B0%D1%81%D0%BD%D0%BE-%D1%87%D1%91%D1%80%D0%BD%D1%8B%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D1%8C%D1%8F&amp;diff=65757</id>
		<title>Левосторонние красно-чёрные деревья</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%B2%D0%BE%D1%81%D1%82%D0%BE%D1%80%D0%BE%D0%BD%D0%BD%D0%B8%D0%B5_%D0%BA%D1%80%D0%B0%D1%81%D0%BD%D0%BE-%D1%87%D1%91%D1%80%D0%BD%D1%8B%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D1%8C%D1%8F&amp;diff=65757"/>
				<updated>2018-05-23T22:54:40Z</updated>
		
		<summary type="html">&lt;p&gt;138.197.160.42: /* Вставка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} модификация [[Красно-черное дерево|красно-черных деревьев]], имеющая ряд преимуществ на классической структурой. Разработана Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&amp;lt;/tex&amp;gt; году.&lt;br /&gt;
  }}&lt;br /&gt;
==Преимущества==&lt;br /&gt;
* необходимо менее &amp;lt;tex&amp;gt;80&amp;lt;/tex&amp;gt; строчек кода для реализации структуры &lt;br /&gt;
* более быстрая вставка, удаление элементов&lt;br /&gt;
* простота&lt;br /&gt;
&lt;br /&gt;
==Вращения==&lt;br /&gt;
Чтобы поддерживать красно-черные двоичное деревья поиска необходимо соблюдать следующие инвариантные свойства при вставке и удалении:&lt;br /&gt;
* Ни один обход от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&gt;
* Количество черных узлов на каждом таком пути одинаково.&lt;br /&gt;
Из этих инвариантов следует, что длина каждого пути от корня до листьев в красно-черном дереве с &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; узлами не превышает &amp;lt;tex&amp;gt;2 \cdot \log(N)&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Основные операции, используемые алгоритмами сбалансированного дерева для поддержания баланса при вставке и удалении, называются вращениями. Эти операции трансформируют &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;-узел,левый потомок которого окрашен в красный, в  &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;-узел, правый потомок которого окрашен в красный и наоборот.  Вращения сохраняют два указанных выше инварианта, не изменяют поддеревья узла.&lt;br /&gt;
===Псевокод===&lt;br /&gt;
[[File:rotateRight.png|310px|thumb|upright|Rotate Right]]&lt;br /&gt;
   '''Node''' rotateRight( h : '''Node''') :&lt;br /&gt;
       x = h.left&lt;br /&gt;
       h.left= x.right&lt;br /&gt;
       x.right= h&lt;br /&gt;
       x.color = h.color&lt;br /&gt;
       h.color = RED&lt;br /&gt;
    '''return''' x&lt;br /&gt;
[[File:rotateLeft.png|310px|thumb|upright|Rotate Left]]&lt;br /&gt;
   '''Node''' rotateLeft( h : '''Node''') :&lt;br /&gt;
       x = h.right&lt;br /&gt;
       h.right = x.left&lt;br /&gt;
       x.left = h&lt;br /&gt;
       x.color = h.color&lt;br /&gt;
       h.color = RED&lt;br /&gt;
   '''return''' x&lt;br /&gt;
&lt;br /&gt;
==Переворот цветов==&lt;br /&gt;
&lt;br /&gt;
В красно-черных деревьях используется такая  операция как '''Переворот цветов''' &amp;lt;tex&amp;gt;(flip color)&amp;lt;/tex&amp;gt; , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  при любом обходе от корня до листьев дерева, но может привести к появлению двух последовательных красных узлов. &lt;br /&gt;
[[File: ColorFlip.png|320px|thumb|upright| Color Flip]]&lt;br /&gt;
&lt;br /&gt;
  '''void''' flipColors( h : '''Node''' h) :&lt;br /&gt;
       h.color = '''!''' h.color&lt;br /&gt;
       h.left.color =  '''!''' h.left.color&lt;br /&gt;
       h.right.color = &amp;lt;tex&amp;gt; !&amp;lt;/tex&amp;gt; h.right.color&lt;br /&gt;
&lt;br /&gt;
==Вставка==&lt;br /&gt;
Вставка в ЛСКЧД базируется на &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; простых операциях:&lt;br /&gt;
&lt;br /&gt;
*Вставка нового узла к листу дерева:&lt;br /&gt;
Если высота узла  нулевая, возвращаем новый красный узел.&lt;br /&gt;
[[File:insertNode.png|310px|thumb|upright|Вставка нового узла]]&lt;br /&gt;
&lt;br /&gt;
  if (h == null)&lt;br /&gt;
       return new Node(key, value, RED);&lt;br /&gt;
&lt;br /&gt;
*Расщепление узла с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;-я потомками:&lt;br /&gt;
Если левый предок и правый предок  красные, запускаем вращение цветов от текущего узла.&lt;br /&gt;
[[File:Split4node.png|310px|thumb|upright|Расщепление узла]]&lt;br /&gt;
  if (isRed(h.left) &amp;amp;&amp;amp; isRed(h.right))&lt;br /&gt;
      colorFlip(h);&lt;br /&gt;
&lt;br /&gt;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&lt;br /&gt;
Если правый предок красный, вращаем текущую вершину влево.&lt;br /&gt;
  if (isRed(h.right))&lt;br /&gt;
      h = rotateLeft(h);&lt;br /&gt;
&lt;br /&gt;
*Балансировка узла с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;-я потомками:&lt;br /&gt;
[[File:Balance4node.png|310px|thumb|Балансировка]]&lt;br /&gt;
Если левый предок красный и левый предок левого предка красный, то вращаем текущую вершину вправо.&lt;br /&gt;
  if (isRed(h.left) &amp;amp;&amp;amp; isRed(h.left.left))&lt;br /&gt;
      h = rotateRight(h);&lt;br /&gt;
   &lt;br /&gt;
===Псевдокод===&lt;br /&gt;
  '''void''' insert( '''key''' : Key, '''value''' : Value ): &lt;br /&gt;
         root = insert(root, key, value)&lt;br /&gt;
         root.color = BLACK&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  '''Node''' insert( h : '''Node''', key : '''Key''', value : '''Value'''):&lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Вставка нового узла к листу дерева&amp;lt;/span&amp;gt;&lt;br /&gt;
      '''if''' h == ''null''     &lt;br /&gt;
          '''return''' '''new''' Node(key, value)&lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Расщепление узла с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;-я потомками&amp;lt;/span&amp;gt;&lt;br /&gt;
      '''if''' isRed(h.left) '''&amp;amp;&amp;amp;''' isRed(h.right)&lt;br /&gt;
          colorFlip(h)&lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Стандартная вставка [[Дерево поиска, наивная реализация|в дереве поиска]]&amp;lt;/span&amp;gt;&lt;br /&gt;
      '''int''' cmp = key.compareTo(h.key) &lt;br /&gt;
      '''if'''  cmp == 0&lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' cmp &amp;lt; 0 &lt;br /&gt;
              h.left = insert(h.left, key, value)  &lt;br /&gt;
          '''else''' &lt;br /&gt;
              h.right = insert(h.right, key, value)&lt;br /&gt;
           &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Принудительное вращение влево&amp;lt;/span&amp;gt;&lt;br /&gt;
          '''if''' isRed(h.right) '''&amp;amp;&amp;amp;''' '''!'''isRed(h.left)    &lt;br /&gt;
              h = rotateLeft(h)&lt;br /&gt;
           &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Балансировка узла с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;-я потомками&amp;lt;/span&amp;gt;&lt;br /&gt;
          '''if''' isRed(h.left) '''&amp;amp;&amp;amp;''' isRed(h.left.left)&lt;br /&gt;
              h = rotateRight(h)&lt;br /&gt;
  '''return''' ''h''&lt;br /&gt;
&lt;br /&gt;
==Поиск==&lt;br /&gt;
Поиск в левосторонних красно-черных деревьях эквивалентен поиску в [[Дерево поиска, наивная реализация|наивной реализации дерева поиска]].&lt;br /&gt;
Для поиска элемента в красно-черных деревьях дереве поиска можно воспользоваться циклом, проходит от вершины до искомого элемента. Если же элемент отсутствует  цикл пройдет то листа дерева и прервется. Для каждого узла цикл сравнивает значение его ключа с искомым ключом. Если ключи одинаковы, то функция возвращает текущий узел, в противном случае цикл повторяет для левого или правого поддерева. Узлы, которые посещает функция образуют нисходящий путь от корня, так что время ее работы &amp;lt;tex&amp;gt;O(h)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; {{---}} высота дерева.&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Value''' search(key : '''Key'''):&lt;br /&gt;
     '''Node''' x = root&lt;br /&gt;
     '''while''' (x '''!'''= null)&lt;br /&gt;
       '''int''' cmp = key.compareTo(x.key)&lt;br /&gt;
       '''if''' (cmp == 0)&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' (cmp &amp;lt; 0)&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' (cmp &amp;gt; 0) &lt;br /&gt;
               x = x.right&lt;br /&gt;
 '''return''' ''null''&lt;br /&gt;
&lt;br /&gt;
==Удаление==&lt;br /&gt;
===Исправление правых красных связей===&lt;br /&gt;
*Использование Переворота цветов и вращений  сохраняет баланс черной связи.&lt;br /&gt;
*После удаления необходимо исправить правые красные связи и устранить узлы с &amp;lt;tex&amp;gt;4-&amp;lt;/tex&amp;gt;я потомками&lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Исправление правых красных связей&amp;lt;/span&amp;gt;&lt;br /&gt;
   '''Node''' fixUp(h : '''Node'''){  &lt;br /&gt;
       '''if''' (isRed(h.right))  &lt;br /&gt;
           h = rotateLeft(h);  &lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Вращение &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;-ой красной пары пары&amp;lt;/span&amp;gt;&lt;br /&gt;
       '''if''' (isRed(h.left) '''&amp;amp;&amp;amp;''' isRed(h.left.left))&lt;br /&gt;
           h = rotateRight(h);  &lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Балансировка узла с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;-я потомками&amp;lt;/span&amp;gt;&lt;br /&gt;
       '''if''' (isRed(h.left) '''&amp;amp;&amp;amp;''' isRed(h.right))&lt;br /&gt;
           colorFlip(h);  &lt;br /&gt;
   '''return''' h; &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
===Удаление максимума===&lt;br /&gt;
* Спускаемся вниз по правому краю  дерева.&lt;br /&gt;
* Если поиск заканчивается на узле с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;-мя или &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;-ю потомками, просто удаляем узел.&lt;br /&gt;
&lt;br /&gt;
[[File:34-nodeRemove.png|310px|thumb|center| Узлы до и после удаления]] &lt;br /&gt;
* Удаление узла с &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;-я потомками разрушает баланс&lt;br /&gt;
Соответственно спускаясь вниз по дереву необходимо поддерживать следующий инвариант : количество потомков узла не должно быть ровно &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;-м.&lt;br /&gt;
[[File:changeNode.png|600px|thumb|center| ]] &lt;br /&gt;
 &lt;br /&gt;
Будем поддерживать инвариант : Для любого узла либо сам узел, либо правый предок узла '''красный'''.&lt;br /&gt;
Будем придерживаться тактики , что удалять лист легче, чем внутренний узел.&lt;br /&gt;
&lt;br /&gt;
Заметим, что если правый потомок вершины и правый потомок правого потомка вершины черные, необходимо переместить левую красную ссылку вправо для сохранения инварианта.&lt;br /&gt;
[[File:MinEasy.png|400px|thumb|right| Перемещение красной ссылки. Простой случай]] &lt;br /&gt;
&lt;br /&gt;
[[File:MinHard.png|400px|thumb|right| Перемещение красной ссылки. Сложный случай]]&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''void''' deleteMax()              &lt;br /&gt;
     root = deleteMax(root);         &lt;br /&gt;
     root.color = BLACK;               &lt;br /&gt;
&lt;br /&gt;
 '''Node''' moveRedLeft(h : '''Node''')&lt;br /&gt;
     colorFlip(h);                     &lt;br /&gt;
     if (isRed(h.right.left)                &lt;br /&gt;
         h.right = rotateRight(h.right);       &lt;br /&gt;
         h = rotateLeft(h);                   &lt;br /&gt;
         colorFlip(h);                          &lt;br /&gt;
 '''return''' h;                                              &lt;br /&gt;
&lt;br /&gt;
 '''Node''' deleteMax(h : '''Node''')&lt;br /&gt;
     if (isRed(h.left))                                         &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//вращаем все 3-вершины вправо&amp;lt;/span&amp;gt;&lt;br /&gt;
         h = rotateRight(h);&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//поддерживаем инвариант (h должен быть красным)&amp;lt;/span&amp;gt;&lt;br /&gt;
     if (h.right == null)   &lt;br /&gt;
         return null;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//заимствуем у брата если необходимо&amp;lt;/span&amp;gt;&lt;br /&gt;
     if (!isRed(h.right) '''&amp;amp;&amp;amp;''' !isRed(h.right.left)) &lt;br /&gt;
         h = moveRedRight(h);&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// опускаемся на один уровень глубже &amp;lt;/span&amp;gt;&lt;br /&gt;
     h.left = deleteMax(h.left); &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//исправление правых красных ссылок и 4-вершин на пути вверх&amp;lt;/span&amp;gt;&lt;br /&gt;
     '''return''' fixUp(h);&lt;br /&gt;
&lt;br /&gt;
==Удаление минимума==&lt;br /&gt;
Поддерживаем инвариант: вершина или левый ребенок вершины красный.&lt;br /&gt;
&lt;br /&gt;
Заметим, что если  левый потомок вершины и левый потомок левого потомка вершины черные, необходимо переместить красную ссылку для сохранения инварианта.&lt;br /&gt;
[[File:MoveRedLeftEasy.png.png |400px|thumb|upright|Перемещение красной ссылки. Простой случай]]&lt;br /&gt;
[[File:MoveRedLeftNoEasy.png|400px|thumb|upright|Перемещение красной ссылки. Сложный случай]]&lt;br /&gt;
===Псевдокод=== &lt;br /&gt;
 '''Node''' moveRedLeft(h : '''Node''')&lt;br /&gt;
     colorFlip(h);&lt;br /&gt;
     if (isRed(h.right.left))&lt;br /&gt;
         h.right = rotateRight(h.right);&lt;br /&gt;
         h = rotateLeft(h);&lt;br /&gt;
         colorFlip(h);&lt;br /&gt;
 '''return''' h;&lt;br /&gt;
&lt;br /&gt;
 '''void''' deleteMin()&lt;br /&gt;
     root = deleteMin(root);&lt;br /&gt;
     root.color = BLACK;&lt;br /&gt;
&lt;br /&gt;
 '''Node''' deleteMin(h : '''Node''')&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//удаляем узел на нижнем уровне(h должен быть красным по инварианту)&amp;lt;/span&amp;gt;&lt;br /&gt;
     if (h.left == ''null'')    &lt;br /&gt;
         '''return''' ''null'';&lt;br /&gt;
      &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//Если необходимо, пропушим  красную ссылку вниз&amp;lt;/span&amp;gt;&lt;br /&gt;
     '''if  !'''isRed(h.left) '''&amp;amp;&amp;amp;  !'''isRed(h.left.left)&lt;br /&gt;
          h = moveRedLeft(h);&lt;br /&gt;
      &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;//опускаемся на уровень ниже &amp;lt;/span&amp;gt;&lt;br /&gt;
     h.left = deleteMin(h.left);&lt;br /&gt;
 '''return''' fixUp(h);&lt;br /&gt;
&lt;br /&gt;
==Асимптотика==&lt;br /&gt;
Асимптотика методов в левосторонних красно-черных деревьях эквивалентна асимптотике [[Красно-черное дерево|левосторонних красно-черных деревьях]].&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Robert Sedgewick &amp;quot;Left-leaning Red-Black Trees&amp;quot; ,Department of Computer Science, Princeton University&lt;br /&gt;
== См.также ==&lt;br /&gt;
*[[Красно-черное дерево]]&lt;br /&gt;
*[[Дерево поиска, наивная реализация]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;/div&gt;</summary>
		<author><name>138.197.160.42</name></author>	</entry>

	</feed>