//поиск элемента public SplayNode <T> Search(T key) { SplayNode <T> searchedElement = root; while (searchedElement != null) { //если искомый элемент больше корня, спускаемся в правое поддерево if (searchedElement.Value.CompareTo(key) < 0) { searchedElement = searchedElement.Right; } //если искомый элемент меньше корня, спускаемся в левое поддерево else if (searchedElement.Value.CompareTo(key) > 0) { searchedElement = searchedElement.Left; } //если искомый элемент равен корню, поворачиваем дерево так, что бы искомый элемент стал на место корня и выводим его else if (searchedElement.Value.CompareTo(key) == 0) { Splay(searchedElement); return(searchedElement); } } //если нет такого элемента выводим null return(null); }
public SplayNode <T> SearchDivideElement(T key) { SplayNode <T> searchedElement = root; while (searchedElement != null) { //если искомый элемент больше корня, спускаемся в правое поддерево, если правее никого нет и мы дошли до конца, if (searchedElement.Value.CompareTo(key) < 0) { searchedElement = searchedElement.Right; if (searchedElement.Right == null) { return(searchedElement); } } //если искомый элемент меньше корня, спускаемся в левое поддерево, если левее никого нет, то берем наименьший элемент, больший данному else if (searchedElement.Value.CompareTo(key) > 0) { searchedElement = searchedElement.Left; if (searchedElement.Left == null) { return(searchedElement); } } //если искомый элемент равен корню, поворачиваем дерево так, что бы искомый элемент стал на место корня и выводим его else if (searchedElement.Value.CompareTo(key) == 0) { Splay(searchedElement); return(searchedElement); } } //если нет такого элемента выводим null return(null); }
public void Splay(SplayNode <T> pivotElement) { //пока элемент не встанет на место корня, выполняем повороты, в зависимости от того, как расположен элемент в дереве while (pivotElement.Parent != null) { //если элемент один из сыновей корня if (pivotElement.Parent.Parent == null) { //если элемент левый сын, делаем правый поворот и он становится на место корня, а его отец становится правым сыном if (pivotElement == pivotElement.Parent.Left) { RightRotate(pivotElement.Parent); } //если элемент правый сын, делаем левый поворот и элемент становится на место корня, а его отец становится левым сыном else if (pivotElement == pivotElement.Parent.Right) { LeftRotate(pivotElement.Parent); } } //если элемент, его отец и дедушка лежат на одной ветке, то делаем два правых или два левых поворота //zig-zig //если они все лежат на левой ветке делам два правых поворота для отца и дедушки else if (pivotElement == pivotElement.Parent.Left && pivotElement.Parent == pivotElement.Parent.Parent.Left) { //после первого правого поворота элемент становится на место своего отца, а отец становится правым сыном элемента RightRotate(pivotElement.Parent.Parent); //после второго правого поворота элемент становится на место дедушки RightRotate(pivotElement.Parent); } //если они лежат на правой ветке делаем два левых поворота для отца и дедушки else if (pivotElement == pivotElement.Parent.Right && pivotElement.Parent == pivotElement.Parent.Parent.Right) { //после первого левого поворота элемент становится отцом своего отца, а отец, левым сыном элемента LeftRotate(pivotElement.Parent.Parent); //после второго левого поворота, элемент становится на место дедушки LeftRotate(pivotElement.Parent); } //zig-zag //если элемент-правый сын левого сына, делаем сначала левый поворот для отца, зател правй поворот для дедушки else if (pivotElement == pivotElement.Parent.Right && pivotElement.Parent == pivotElement.Parent.Parent.Left) { //после левого поворота элемент становится отцом своего отца, а отец левым сыном элемента LeftRotate(pivotElement.Parent); // элемент, его отец и дедушка лежат на левой ветке, делаем один правй поворот, т.к. элемент находится между отцом и дедушкой, //в итоге становится на место своего дедушки RightRotate(pivotElement.Parent); } //если элемент-левый сын правого сына, то делаем сначала правый поворот для отца, затем левый поворот для дедушки else if (pivotElement == pivotElement.Parent.Left && pivotElement.Parent == pivotElement.Parent.Parent.Right) { //после правого поворота элемент становится отцом своего отца, а отец правым сыном элемента RightRotate(pivotElement.Parent); // элемент, его отец и дедушка лежат на правой ветке, делаем один левый поворот, т.к. элемент находится между отцом и дедушкой, //в итоге становится на место своего дедушки LeftRotate(pivotElement.Parent); } } }
//ищет максимальный элемент public SplayNode <T> Max(SplayNode <T> localRoot) { SplayNode <T> maximum = localRoot; //спускаемся вниз вправо до конца, достаем самый большой элемент while (maximum.Right != null) { maximum = maximum.Right; } return(maximum); }
/* * //печатает дерево на экран * public void preOrder(SplayNode<T> root) * { * //сначала печатает корень, затем левую ветку, потом правую ветку * if (root != null) * { * Console.WriteLine(root.Value); * preOrder(root.Left); * preOrder(root.Right); * Console.WriteLine(""); * } * }*/ //ищет минимальный элемент public SplayNode <T> Min(SplayNode <T> localRoot) { SplayNode <T> minimum = localRoot; //спускаемся вниз влево до конца, достаем самый маленький элемент while (minimum.Left != null) { minimum = minimum.Left; } return(minimum); }
//разделение дерева public Tuple <SplayNode <T>, SplayNode <T> > Split(T key) { //разделяемый элемент SplayNode <T> element = SearchDivideElement(key); //поворачиваем дерево так, что бы разделяемый элемент встал на место корня Splay(element); SplayNode <T> item21 = element.Left; if (element != null) { element.Left.Parent = null; element.Left = null; } return(new Tuple <SplayNode <T>, SplayNode <T> >(item21, element)); }
//вставка нового элемента public void Insert(T key) { //переменная для поиска места родителя вставляемого элемента SplayNode <T> preInsertPlace = null; //переменная для поиска места вставки элемента SplayNode <T> insertPlace = root; //ищем место для нового элемента while (insertPlace != null) { preInsertPlace = insertPlace; //если элемент больше или равен корню, спускаемся в правое поддерево if (insertPlace.Value.CompareTo(key) <= 0) { insertPlace = insertPlace.Right; } //если элемент меньше корня спускаемся в левое поддерево else if (insertPlace.Value.CompareTo(key) > 0) { insertPlace = insertPlace.Left; } } //создаем новый элемент SplayNode <T> insertElement = new SplayNode <T>(key); //родитель insertElement.Parent = preInsertPlace; //если предыдущего элемента нет, то вставляемый элемент-корень дерева if (preInsertPlace == null) { root = insertElement; } //если новый элемент не меньше своего родителя, то он правый сын else if (preInsertPlace.Value.CompareTo(insertElement.Value) < 0) { preInsertPlace.Right = insertElement; } //если новый элемент меньше своего родителя, то он левый сын else if (preInsertPlace.Value.CompareTo(insertElement.Value) > 0) { preInsertPlace.Left = insertElement; } //поворачиваем дерево так, что бы вставляемый элемент встал на место корня Splay(insertElement); }
//объединение двух деревьев public SplayTree <T> Merge(SplayTree <T> tree11, SplayTree <T> tree22) { var tree1 = new SplayTree <T>(); var tree2 = new SplayTree <T>(); //ищем максимальные и минимальные элементы деревьев var min1 = Min(tree11.root); var max1 = Max(tree11.root); var min2 = Min(tree22.root); var max2 = Max(tree22.root); //Для корректной работы,все ключи одного дерева должны быть меньше всех ключей другого дерева //если самый маленький элемент 1 дерева больше самого болшого элемента 2 дерева //то все ключи 2 дерева меньше всех ключей 1 дерева if (min1.Value.CompareTo(max2.Value) > 0) { tree1 = tree22; tree2 = tree11; } //если самый маленький элемент 2 дерева больше самого болшого элемента 1 дерева //то все ключи 1 дерева меньше всех ключей 2 дерева else if (min2.Value.CompareTo(max1.Value) > 0) { tree1 = tree11; tree2 = tree22; } //иначе нельзя соеденить эти деревья else { return(null); } //находим наибольший элемент 1 дерева SplayNode <T> element = Max(tree1.root); //поворачиваем дерево так что бы все его элементы были в левой ветке Splay(element); //правой веткой 1 дерева становится 2 дерево element.Right = tree2.root; //родитель 2 дерева-наибольший желемент 1 дерева tree22.root.Parent = element; return(tree1); }
public void Transplat(SplayNode <T> localParent, SplayNode <T> localChild) { if (localParent.Parent == null) { root = localChild; } else if (localParent == localParent.Parent.Left) { localParent.Parent.Left = localChild; } else if (localParent == localParent.Parent.Right) { localParent.Parent.Right = localChild; } if (localChild != null) { localChild.Parent = localParent.Parent; } }
//правый поворот public void RightRotate(SplayNode <T> localRoot) { //элемент, который в конце должен оказаться на месте корня SplayNode <T> leftChild = localRoot.Left; if (leftChild != null) { //правое поддерево нужного элемента становится левым поддеревом текущего корня localRoot.Left = leftChild.Right; //ставим ссылку на родителя, если есть элементы в правом поддереве нужного элемента if (leftChild.Right != null) { leftChild.Right.Parent = localRoot; } //элемент, который в конце должен оказаться на месте корня, становится выше текущего корня leftChild.Parent = localRoot.Parent; } //если текущий корень был корнем всего дерева, то элемент, который в конце должен оказаться на месте корня, становится на место корня if (localRoot.Parent == null) { root = leftChild; } //если текущий корень был левым сыном, то элемент, который в конце должен оказаться на месте корня становится левым сыном else if (localRoot == localRoot.Parent.Left) { localRoot.Parent.Left = leftChild; } //если текущий корень был правым сыном, то элемент, который в конце должен оказаться на месте корня становится правым сыном else if (localRoot == localRoot.Parent.Right) { localRoot.Parent.Right = leftChild; } //текущий корень становится правым сыном элемента, который в конце должен оказаться на месте корня if (leftChild != null) { leftChild.Right = localRoot; } localRoot.Parent = leftChild; }
//удаление элемента public void Remove(T key) { //ищем элемент в дереве SplayNode <T> removeElement = Search(key); if (removeElement != null) { //поворачиваем дерево так, что бы удаляемый элемент встал на место корня if (removeElement.Right == null) { Transplat(removeElement, removeElement.Left); //? } else if (removeElement.Left == null) { Transplat(removeElement, removeElement.Left); //? } else { //новый корень-минимальный элемент, который больше удаляемого элемента SplayNode <T> newLocalRoot = Min(removeElement.Right); if (newLocalRoot.Parent != removeElement) { Transplat(newLocalRoot, newLocalRoot.Right); //правая ветка у нового корня такая же как и правая ветка удаляемого элемента newLocalRoot.Right = removeElement.Right; newLocalRoot.Right.Parent = newLocalRoot; } Transplat(removeElement, newLocalRoot); //левая ветка у нового корня такая же как и левая ветка удаляемого элемента newLocalRoot.Left = removeElement.Left; newLocalRoot.Left.Parent = newLocalRoot; Splay(newLocalRoot); } } }
public SplayNode(T value) { Value = value; Left = Right = Parent = null; }