static void Main(string[] args) { while (true) { string[] values = { "andrew", "kisya", "kotik", "evgen", "wkola", "ryry", "kiol", "sam", "slava", "baking", "brut", "truba", "lul", "poggers","pog","pogu", "strong", "easy", "hard", "imp" }; var tree = new AVLTree.AVLTree(); Random rand = new Random(); string entered = ""; while (true) { Console.Clear(); tree.Draw(); Console.SetCursorPosition(0, 15); Console.WriteLine("Press 0 for restart"); Console.WriteLine("Entered values: " + entered); Console.Write("Enter the value: "); try { int value = Convert.ToInt32(Console.ReadLine()); if (value == 0) { break; } tree.Add(value); entered += value.ToString() + ", "; } catch { continue; } } } }
static void Main(string[] args) { //int[] nums = { 64, 28, 26, 80, 50, 77, 82, 3, 65, 16, 9, 87, 38, 67, 69, 49, 10, 79, 15, 62, 30, 48, 52, 31, 19, 35, 59, 41, 97, 92, 22, 37, 7, 70, 78, 21, 72, 96, 91, 73, 4, 54, 27, 75, 46, 44, 51, 84, 57, 2, 42, 93, 33, 13, 88, 94, 55, 43, 5, 40, 18, 36, 76, 60, 86, 45, 25, 99, 39, 95, 71, 66, 81, 90, 6, 53, 24, 11, 56, 98, 14, 20, 83, 61, 23, 74, 68, 12, 17, 29, 34, 32, 8, 0, 63, 85, 89, 47, 58, 1 }; int[] nums = { 15, 10, 24, 25, 9, 13, 14, 23, 0, 5, 4, 8, 11, 17, 2, 12, 21, 16, 22, 6, 3, 18, 7, 20, 1, 19 }; //int[] nums = { 1, 0, 6, 3, 9, 2, 7, 8, 5, 4 }; //int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,12}; //int[] nums = { 7, 6, 5, 4, 3, 2, 1 }; //int[] nums = {1,5,7,6,8,9}; var tree = new AVLTree<int>(); Console.Write("AVL tree\n\nWild list:\n "); foreach (var i in nums) { Console.Write(i + " "); tree.Add(i); } Console.Write("\n\nSorted list:\n "); foreach (var i in tree) Console.Write(i + " "); Console.Write("\n\nTree count:\n {0}", tree.Count); Console.Write("\n\nVertical tree draw:\n "); Console.Write(tree.ToString()); Console.Write("\n\nTree root's historical balances:\n "); foreach (int i in tree.HistoricalBalances) Console.Write("{0} ", i); Console.Write("\n\nHistorical roots:\n "); foreach (var i in tree.HistoricalRoots) Console.Write("{0} ", i); Console.ReadKey(); }
public AVLTreeNode(TNode value, AVLTreeNode <TNode> parent, AVLTree <TNode> tree) { Value = value; Parent = parent; _tree = tree; }
static void Main(string[] args) { AVLTree tree = new AVLTree(); bool flag = true; while (flag) { Console.Clear(); Console.WriteLine("Demo: AVLTree of Integer"); Console.WriteLine("--------------------------------"); Console.WriteLine("1 - Insert node"); Console.WriteLine("2 - Delete node"); Console.WriteLine("3 - Search node"); Console.WriteLine("4 - Traverse Tree In-Order"); Console.WriteLine("5 - Display Tree"); Console.WriteLine("6 - Exit"); Console.WriteLine("--------------------------------"); ConsoleKeyInfo cki = Console.ReadKey(true); switch (cki.Key) { case ConsoleKey.D1: Console.WriteLine("Enter node to insert:"); string insertInput = Console.ReadLine(); if (Int32.TryParse(insertInput, out int insertNode)) { tree.Insert(insertNode); Console.WriteLine("Node " + insertNode + " has been inserted."); } else { Console.WriteLine("Invalid input. Enter integer number"); } Console.WriteLine("\nPress any key..."); Console.ReadLine(); break; case ConsoleKey.D2: Console.WriteLine("Enter node to delete:"); string deleteInput = Console.ReadLine(); if (Int32.TryParse(deleteInput, out int deleteNode)) { if (tree.Search(deleteNode) == null) { Console.WriteLine("No such node in the tree"); } else { tree.Delete(deleteNode); Console.WriteLine("Node " + deleteNode + " has been deleted."); } } else { Console.WriteLine("Invalid input. Enter integer number"); } Console.WriteLine("\nPress any key..."); Console.ReadLine(); break; case ConsoleKey.D3: tree.PrintTree(); Console.WriteLine("Enter node to search:"); string getInput = Console.ReadLine(); if (Int32.TryParse(getInput, out int getNode)) { if (tree.Search(getNode) != null) { Console.WriteLine("Node " + getNode + " is present in the tree"); } else { Console.WriteLine("No such node in the tree"); } } else { Console.WriteLine("Invalid input. Enter integer number"); } Console.WriteLine("\nPress any key..."); Console.ReadLine(); break; case ConsoleKey.D4: Console.WriteLine("Current tree In-Order traverse:"); tree.TraverseInOrder(); Console.WriteLine("\nPress any key..."); Console.ReadLine(); break; case ConsoleKey.D5: Console.WriteLine("Current tree(from left to right):"); tree.PrintTree(); Console.WriteLine("\nPress any key..."); Console.ReadLine(); break; case ConsoleKey.D6: flag = false; break; default: Console.WriteLine("Invalid menu item, enter numbers 1-4"); Console.WriteLine("\nPress any key..."); Console.ReadLine(); break; } } }
/// <summary> /// Deletes the given key from the tree, if present. /// </summary> /// <param name="key"></param> /// <returns>True if the depth of the tree decreased.</returns> public bool Delete(int key) { if (this.isHead) { // empty tree if (this.rightChild == null) { return(false); } // delete recursively from the tree else { return(this.rightChild.Delete(key)); } } // recursively try to find and delete the key switch (key.CompareTo(this.key)) { // look in the right subtree case 1: { // key is not in the tree, do nothing if (rightChild == null) { break; } // delete the key from the right subtree bool depthDecreased = rightChild.Delete(key); // check balance if (depthDecreased) { switch (this.balance) { // the node is being balanced, but the depth decreases -> send the information to the upper levels case 1: { balance--; return(true); } // node is being unbalanced to the left, the depth does NOT decrease case 0: { balance--; return(false); } // node is already unbalanced to the left, now double unbalanced -> need to rotate case -1: { balance--; switch (leftChild.balance) { // rotate right, depth decreases case -1: { RotateRight(this); return(true); } // rotate right, depth does NOT decrease case 0: { RotateRight(this); return(false); } // double rotate, depth decreases case 1: { RotateLeft(this.leftChild); RotateRight(this); return(true); } default: return(false); } } default: break; } } break; } // look in the right subtree case -1: { // key is not in the tree, do nothing if (leftChild == null) { break; } // delete the key from the left subtree bool depthDecreased = leftChild.Delete(key); // check balance if (depthDecreased) { switch (this.balance) { // the node is being balanced, but the depth decreases -> send the information to the upper levels case -1: { balance++; return(true); } // node is being unbalanced to the right, the depth does NOT decrease case 0: { balance++; return(false); } // node is already unbalanced to the right, now double unbalanced -> need to rotate case 1: { balance++; switch (rightChild.balance) { // rotate left, depth decreases case 1: { RotateLeft(this); return(true); } // rotate left, depth does NOT decrease case 0: { RotateLeft(this); return(false); } // double rotate, depth decreases case -1: { RotateRight(this.rightChild); RotateLeft(this); return(true); } default: return(false); } } default: break; } } break; } // we have found the key, now we will delete it case 0: { // node is leaf, simply delete if ((this.rightChild == null) && (this.leftChild == null)) { if (this.key < parent.key) { parent.leftChild = null; } else { parent.rightChild = null; } return(true); } // node has only a left child, just reconnect it else if (this.rightChild == null) { if (this.key < parent.key) { parent.leftChild = this.leftChild; this.leftChild.parent = this.parent; } else { parent.rightChild = this.leftChild; this.leftChild.parent = this.parent; } return(true); } // node has only a right child, just reconnect it else if (this.leftChild == null) { if (this.key < parent.key) { parent.leftChild = this.rightChild; this.rightChild.parent = this.parent; } else { parent.rightChild = this.rightChild; this.rightChild.parent = this.parent; } return(true); } // node has both children, replace it with a node from the subtree else { int replacementKey; // choose the replacement in the deeper subtree (avoid disbalancing) if (this.balance == -1) { replacementKey = leftChild.findMaxKey(); } else { replacementKey = rightChild.findMinKey(); } // delete the replacement key (it has surely atmost one child) bool depthDecreased = this.Delete(replacementKey); // replace the key in this node by the key of the deleted replacement this.key = replacementKey; // deleting in the subtree might change depth, propagate return(depthDecreased); } } default: break; } return(false); }
/// <summary> /// Inserts the given key into the tree. /// </summary> /// <param name="key"></param> /// <returns>True if the depth of the tree increased.</returns> public bool Insert(int key) { // empty node, simply fill with key if (this.containsKey == false) { this.key = key; this.containsKey = true; // depth increased return(true); } // non-empty node, insert to the correct subtree else { switch (key.CompareTo(this.key)) { // insert to the right subtree case 1: { // create right child if nonexistent if (rightChild == null) { rightChild = new AVLTree(this); } // insert the key to the left subtree bool depthIncreased = rightChild.Insert(key); // check balance if (depthIncreased) { // head does not need to be balanced if (this.isHead == true) { break; } switch (this.balance) { // right subtree was deeper, now increased by another level -> rotation necessary case 1: { this.balance++; // single left rotation if (this.rightChild.balance == 1) { RotateLeft(this); } // double rotation else if (this.rightChild.balance == -1) { RotateRight(this.rightChild); RotateLeft(this); } // balance of the right child cannot be 0, the depth would not increase in such case // tree has been balanced and the depth change does not propagate any further return(false); } case 0: { // right child was balanced, now it will be unbalanced by one (still OK) - propagate the information about depth increase to the upper levels this.balance++; return(true); } case -1: { // right child was unbalanced to the left, now it will be balanced and the depth will stay the same this.balance++; return(false); } default: break; } } break; } // insert to the left subtree (mirror situation) case -1: { // create right child if nonexistent if (leftChild == null) { leftChild = new AVLTree(this); } // insert the key to the left subtree if (leftChild.Insert(key)) { // head does not need to be balanced if (this.isHead == true) { break; } switch (this.balance) { // left subtree was deeper, now increased by another level -> rotation necessary case -1: { this.balance--; // single right rotation if (this.leftChild.balance == -1) { RotateRight(this); } // double rotation else if (this.leftChild.balance == 1) { RotateLeft(this.leftChild); RotateRight(this); } // balance of the left child cannot be 0, the depth would not increase in such case // tree has been balanced and the depth change does not propagate any further return(false); } case 0: { // left child was balanced, now it will be unbalanced by one (still OK) - propagate the information about depth increase to the upper levels this.balance--; return(true); } case 1: { // left child was unbalanced to the right, now it will be balanced and the depth will stay the same this.balance--; return(false); } default: break; } } break; } // key is already in the tree, do nothing case 0: break; default: break; } } return(false); }