由於有些樹是這樣子的:node
這樣子的樹有個壞處就是查詢效率低,由於左邊只有一層,而右邊有3層,這就說明若是查找一個數字大於根元素的數字,那麼查詢判斷就更多。ide
解決方法就是下降兩邊的層數差距:測試
變成這樣。this
那麼如何這樣作呢?3d
若是右邊比左邊層次大於1,進行左旋轉規格:code
若是左邊比右邊層次大於1,進行右旋轉:blog
爲何是這樣處理呢?排序
我拿左旋轉來講:get
左邊是1,右邊是3,那麼須要右邊的給一層給左邊。string
這時候就是6做爲根節點,6做爲根節點,自己呢,就是一顆二叉樹。
這時候呢,6大於4,因此4在6的右邊,而6的左節點確定大於4(原理的根節點)小於6,因此做爲4的左節點代替,4也就成了6的左節點。
右旋轉同理。
就是這樣經過右旋轉以後,可能達不到目標。
看上面這張圖,右旋轉後仍是不平衡,爲何會這樣呢?緣由是這樣的,咱們來看下本質問題,右旋轉幹了什麼?右旋轉實際上是從新分配元素的過程。
看我這種圖紅色部分,實際上是將紅色部門分給了右邊,這時候會存在元素個數差別過大的問題。
那麼這時候該怎麼辦呢?
要讓紅框部分進行左旋轉才行,那麼看代碼吧。
節點模型:
public class Node { public Node left; public Node right; int value; public int Value { get => value; set => this.value = value; } public Node(int value) { this.Value = value; } //中序排序 public void infixOrder() { if (this.left != null) { this.left.infixOrder(); } Console.WriteLine(this); if (this.right != null) { this.right.infixOrder(); } } //左子樹高度 public int leftHeight() { if (left == null) { return 0; } return this.left.height(); } //右子樹高度 public int rightHeight() { if (right == null) { return 0; } return this.right.height(); } //計算高度 public int height() { return Math.Max(left==null?0:this.left.height(),right==null?0:this.right.height())+1; } //進行左旋轉 private void leftRotate() { Node newNode = new Node(value); newNode.left = left; newNode.right = right.left; //將右節點變成根節點 value =right.value; //原先右節點被拋棄 right=right.right; //左節點設置爲 left = newNode; } //進行右旋轉 private void rightRotate() { Node newNode = new Node(value); newNode.left = left.right; newNode.right = right; value = this.left.value; left = left.left; right = newNode; } public override string ToString() { return Value.ToString(); } //增長元素 public void addNode(Node node) { if (node.Value < this.Value) { if (this.left == null) { this.left = node; } else { this.left.addNode(node); } } else { if (this.right == null) { this.right = node; }else { this.right.addNode(node); } } if (rightHeight() > leftHeight() + 1) { if (right.leftHeight() > right.rightHeight()) { right.rightRotate(); } this.leftRotate(); } else if (leftHeight() > rightHeight() + 1) { if (left.rightHeight() > left.leftHeight()) { left.leftRotate(); } this.rightRotate(); } } public Node searchParentNode(int value) { if ((this.left != null && this.left.value == value || (this.right != null && this.right.value == value))) { return this; } else { if (this.value < value && this.left != null) { return this.left.searchParentNode(value); } else if (this.value >= value && this.right != null) { return this.right.searchParentNode(value); } else { return null; } } } //查找元素 public Node searchNode(int value) { if (this.Value == value) { return this; } if (this.Value > value) { if (this.left != null) { return this.right.searchNode(value); } else { return null; } } else { if (this.left != null) { return this.left.searchNode(value); } else { return null; } } } }
樹模型:
public class BinarySortTree { //根節點 Node root; internal Node Root { get => root; set => root = value; } public BinarySortTree(Node root) { this.Root = root; } public BinarySortTree() : this(null) { } public void add(Node node) { if (Root == null) { Root = node; } else { this.Root.addNode(node); } } public void infixOrder() { if (Root == null) { Console.WriteLine("root 爲空"); } else { Root.infixOrder(); } } public Node searchNode(int value) { if (Root==null) { Console.WriteLine("root 爲空"); } return Root.searchNode(value); } public int delRightTreeMin(Node node) { Node tagert = node; while (tagert.left!=null) { tagert = tagert.left; } delNode(tagert.Value); return tagert.Value; } public Node searchParentNode(int value) { if (Root != null) { return Root.searchParentNode(value); } return null; } public void delNode(int value) { if (Root == null) { return; } Node node=searchNode(value); if (node == null) { return; } if (node.Value == Root.Value) { Root = null; return; } Node parent = searchParentNode(value); if (node.left == null && node.right == null) { if (parent.left.Value == value) { parent.left = null; } else { parent.right = null; } } else if (node.left != null && node.right != null) { //刪除左邊最大值或者右邊最小值,而後修改值爲刪除的值 parent.right.Value=delRightTreeMin(node.right); } else { if (node.left != null) { if (parent.left.Value == value) { parent.left = node.left; } else { parent.right = node.left; } } else { if (parent.left.Value == value) { parent.left = node.right; } else { parent.right = node.right; } } } } }
測試代碼:
static void Main(string[] args) { int[] arr = { 10, 11, 7, 6, 8, 9 }; BinarySortTree binarySortTree = new BinarySortTree(); //循環的添加結點到二叉排序樹 for (int i = 0; i < arr.Length; i++) { binarySortTree.add(new Node(arr[i])); } //中序遍歷後的數據 Console.WriteLine("樹的高度=" + binarySortTree.Root.height()); //3 Console.WriteLine("樹的左子樹高度=" + binarySortTree.Root.leftHeight()); // 2 Console.WriteLine("樹的右子樹高度=" + binarySortTree.Root.rightHeight()); // 2 Console.WriteLine("當前的根結點=" + binarySortTree.Root);//8 Console.Read(); }
結果: