<?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=188.227.117.250&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=188.227.117.250&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/188.227.117.250"/>
		<updated>2026-05-19T18:48:04Z</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=66178</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=66178"/>
				<updated>2018-06-27T21:32:04Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
Чтобы поддерживать левосторонние красно-черные двоичные деревья поиска необходимо соблюдать следующие инварианты при вставке и удалении:&lt;br /&gt;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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; узлов, где &amp;lt;tex&amp;gt;2&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;
===Псевдокод===&lt;br /&gt;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66124</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=66124"/>
				<updated>2018-06-20T12:33:25Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вращения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
Чтобы поддерживать левосторонние красно-черные двоичные деревья поиска необходимо соблюдать следующие инварианты при вставке и удалении:&lt;br /&gt;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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; узлов, где &amp;lt;tex&amp;gt;2&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;
===Псевдокод===&lt;br /&gt;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66123</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=66123"/>
				<updated>2018-06-20T12:26:15Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вращения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
Чтобы поддерживать левосторонние красно-черные двоичные деревья поиска необходимо соблюдать следующие инварианты при вставке и удалении:&lt;br /&gt;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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; узлов, где &amp;lt;tex&amp;gt;2&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;
===Псевдокод===&lt;br /&gt;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66122</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=66122"/>
				<updated>2018-06-20T12:25:55Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вращения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
Чтобы поддерживать левосторонние красно-черные двоичные деревья поиска необходимо соблюдать следующие инварианты при вставке и удалении:&lt;br /&gt;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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; узлов, где &amp;lt;tex&amp;gt;2&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;
===Псевдокод===&lt;br /&gt;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66121</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=66121"/>
				<updated>2018-06-20T12:25:42Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вращения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
Чтобы поддерживать левосторонние красно-черные двоичные деревья поиска необходимо соблюдать следующие инварианты при вставке и удалении:&lt;br /&gt;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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; узлов, где tex&amp;gt;2&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;
===Псевдокод===&lt;br /&gt;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66120</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=66120"/>
				<updated>2018-06-20T11:44:50Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Свойства */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
Чтобы поддерживать левосторонние красно-черные двоичные деревья поиска необходимо соблюдать следующие инварианты при вставке и удалении:&lt;br /&gt;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66119</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=66119"/>
				<updated>2018-06-20T11:43:24Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Свойства */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
Чтобы поддерживать левосторонние красно-черные двоичные деревья поиска необходимо соблюдать следующие инварианты при вставке и удалении:&lt;br /&gt;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66118</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=66118"/>
				<updated>2018-06-20T11:42:48Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Свойства */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
Чтобы поддерживать левосторонние красно-черные двоичные деревья поиска необходимо соблюдать следующие инварианты при вставке и удалении:&lt;br /&gt;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66117</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=66117"/>
				<updated>2018-06-20T11:11:22Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66116</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=66116"/>
				<updated>2018-06-20T11:11:05Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Исправление правых красных связей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66115</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=66115"/>
				<updated>2018-06-20T11:10:46Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Исправление правых красных связей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66114</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=66114"/>
				<updated>2018-06-20T11:10:25Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66113</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=66113"/>
				<updated>2018-06-20T11:10:00Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66112</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=66112"/>
				<updated>2018-06-20T11:09:42Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66111</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=66111"/>
				<updated>2018-06-20T11:09:10Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66110</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=66110"/>
				<updated>2018-06-20T11:08:48Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66109</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=66109"/>
				<updated>2018-06-20T11:08:00Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66108</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=66108"/>
				<updated>2018-06-20T11:07:00Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
       '''if''' key = x.key&lt;br /&gt;
           '''return''' x.val&lt;br /&gt;
       '''else'''&lt;br /&gt;
           '''if''' key &amp;lt; x.key&lt;br /&gt;
               x = x.left&lt;br /&gt;
       '''else''' &lt;br /&gt;
           '''if''' key &amp;gt; x.key &lt;br /&gt;
               x = x.right&lt;br /&gt;
     '''return''' ''null''&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66107</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=66107"/>
				<updated>2018-06-20T11:05:43Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Удаление */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
*После удаления необходимо исправить правые красные связи и устранить узлы с &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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66106</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=66106"/>
				<updated>2018-06-20T10:41:08Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key = h.key &lt;br /&gt;
          h.val = value&lt;br /&gt;
      '''else''' &lt;br /&gt;
          '''if''' key &amp;lt; h.key  &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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66105</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=66105"/>
				<updated>2018-06-20T10:38:13Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вставка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
&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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66104</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=66104"/>
				<updated>2018-06-20T10:37:25Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вставка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
*Расщепление узла с &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;
&lt;br /&gt;
*Принудительное вращение влево:&lt;br /&gt;
[[File:Enforce.png|310px|thumb|upright|Принудительное вращение]]&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;
[[File:Balance4node.png|310px|thumb|Балансировка]]&lt;br /&gt;
Если левый предок красный и левый предок левого предка красный, то вращаем текущую вершину вправо.&lt;br /&gt;
&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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66103</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=66103"/>
				<updated>2018-06-20T10:35:53Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66102</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=66102"/>
				<updated>2018-06-20T10:31:42Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&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;
* Ни один путь от корня до листьев дерева не содержит двух последовательных красных узлов.&lt;br /&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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66101</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=66101"/>
				<updated>2018-06-20T10:28:45Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска, гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
==Свойства==&lt;br /&gt;
Красно-чёрным называется бинарное поисковое дерево, у которого каждому узлу сопоставлен дополнительный атрибут — цвет и для которого выполняются следующие свойства:&lt;br /&gt;
*Каждый узел промаркирован красным или чёрным цветом&lt;br /&gt;
*Корень и конечные узлы (листья) дерева — чёрные&lt;br /&gt;
*У красного узла родительский узел — чёрный&lt;br /&gt;
*Все простые пути из любого узла x до листьев содержат одинаковое количество чёрных узлов&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;3&amp;lt;/tex&amp;gt;-узел, левый потомок которого окрашен в красный, в  &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;-узел, правый потомок которого окрашен в красный,вторая операция {{---}} наоборот.  Вращения сохраняют два указанных выше инварианта, не изменяют поддеревья узла.&lt;br /&gt;
&lt;br /&gt;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66100</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=66100"/>
				<updated>2018-06-20T10:28:19Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левостороннее красно-черное дерево {{---}} тип сбалансированного двоичного дерева поиска,гарантирующий такую же асимптотическую сложность операций, как у красно-черного дерева поиска.&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
==Свойства==&lt;br /&gt;
Красно-чёрным называется бинарное поисковое дерево, у которого каждому узлу сопоставлен дополнительный атрибут — цвет и для которого выполняются следующие свойства:&lt;br /&gt;
*Каждый узел промаркирован красным или чёрным цветом&lt;br /&gt;
*Корень и конечные узлы (листья) дерева — чёрные&lt;br /&gt;
*У красного узла родительский узел — чёрный&lt;br /&gt;
*Все простые пути из любого узла x до листьев содержат одинаковое количество чёрных узлов&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;3&amp;lt;/tex&amp;gt;-узел, левый потомок которого окрашен в красный, в  &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;-узел, правый потомок которого окрашен в красный,вторая операция {{---}} наоборот.  Вращения сохраняют два указанных выше инварианта, не изменяют поддеревья узла.&lt;br /&gt;
&lt;br /&gt;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66085</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=66085"/>
				<updated>2018-06-18T12:57:46Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
*Все простые пути из любого узла x до листьев содержат одинаковое количество чёрных узлов&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;3&amp;lt;/tex&amp;gt;-узел, левый потомок которого окрашен в красный, в  &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;-узел, правый потомок которого окрашен в красный,вторая операция {{---}} наоборот.  Вращения сохраняют два указанных выше инварианта, не изменяют поддеревья узла.&lt;br /&gt;
&lt;br /&gt;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66084</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=66084"/>
				<updated>2018-06-18T12:55:26Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
*Все простые пути из любого узла x до листьев содержат одинаковое количество чёрных узлов&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66083</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=66083"/>
				<updated>2018-06-18T12:51:34Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
      '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
      '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66082</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=66082"/>
				<updated>2018-06-18T12:51:07Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
       '''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
       '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66081</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=66081"/>
				<updated>2018-06-18T12:50:46Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
       ''if''' key &amp;gt; h.key &lt;br /&gt;
          cmp = 1&lt;br /&gt;
       '''else'''&lt;br /&gt;
          cmp = 0&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66080</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=66080"/>
				<updated>2018-06-18T12:47:43Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вставка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66079</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=66079"/>
				<updated>2018-06-18T12:47:23Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66078</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=66078"/>
				<updated>2018-06-18T12:46:49Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Удаление минимума */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66077</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=66077"/>
				<updated>2018-06-18T12:46:31Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Удаление */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66076</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=66076"/>
				<updated>2018-06-18T12:46:06Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66075</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=66075"/>
				<updated>2018-06-18T12:45:23Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66074</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=66074"/>
				<updated>2018-06-18T12:44:52Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66073</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=66073"/>
				<updated>2018-06-18T12:43:07Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вставка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66072</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=66072"/>
				<updated>2018-06-18T12:42:24Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66071</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=66071"/>
				<updated>2018-06-18T12:41:05Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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 = '''!''' 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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66070</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=66070"/>
				<updated>2018-06-18T12:39:51Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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_2(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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66069</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=66069"/>
				<updated>2018-06-18T12:37:15Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  на любом пути от корня до листа, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66068</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=66068"/>
				<updated>2018-06-18T12:36:24Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  при любом обходе от корня до листьев дерева, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66067</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=66067"/>
				<updated>2018-06-18T12:34:47Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  при любом обходе от корня до листьев дерева, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66066</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=66066"/>
				<updated>2018-06-18T12:34:32Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  при любом обходе от корня до листьев дерева, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
  '''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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66065</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=66065"/>
				<updated>2018-06-18T12:34:15Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  при любом обходе от корня до листьев дерева, но может привести к появлению двух последовательных красных узлов.&lt;br /&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;
  '''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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66064</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=66064"/>
				<updated>2018-06-18T12:33:56Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
В красно-черных деревьях используется такая  операция как '''переворот цветов''' , которая инвертирует цвет узла и двух его детей.  Она не изменяет количество черных узлов  при любом обходе от корня до листьев дерева, но может привести к появлению двух последовательных красных узлов. &lt;br /&gt;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&lt;br /&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;
  '''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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66063</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=66063"/>
				<updated>2018-06-18T12:33:41Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Переворот цветов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
==Переворот цветов==&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;
  '''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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	<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=66062</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=66062"/>
				<updated>2018-06-18T12:33:01Z</updated>
		
		<summary type="html">&lt;p&gt;188.227.117.250: /* Вращения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =  Левосторонние красно-черные деревья {{---}} двоичные деревья поиска, в котором баланс осуществляется на основе &amp;quot;цвета&amp;quot; узла дерева, который принимает только два значения: &amp;quot;красный&amp;quot; и &amp;quot;чёрный&amp;quot;. Данный тип [[Красно-черное дерево|красно-черных деревьев]] имеет ряд преимуществ над классической структурой. Разработан Робертом Соджевиском в &amp;lt;tex&amp;gt;2008&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;
==Переворот цветов==&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;
[[File: ColorFlip.png|320px|thumb|upright| Переворот цветов]]&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;
* Если поиск заканчивается на узле с &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;
*[[Красно-черное дерево]]&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;/div&gt;</summary>
		<author><name>188.227.117.250</name></author>	</entry>

	</feed>