二叉搜索樹也叫二叉查找樹或者二叉排序樹,它要麼是一顆空樹,要麼知足如下幾點:
1.若任意節點的左子樹不空,則左子樹上全部節點的值均小於它的根節點的值。
2.若任意節點的右子樹不空,則右子樹上全部節點的值均大於它的根節點的值。
3.任意節點的左、右子樹也分別爲二叉搜索樹。
4.沒有鍵值相等的節點。 java
1.二叉搜索樹的存儲結構微信
public class BinarySearchTree { public static Node root; public BinarySearchTree(){ this.root = null; } } class Node{ int data; Node left; Node right; public Node(int data){ this.data = data; left = null; right = null; } }
2.二叉搜索樹的插入
a.循環二分查找到須要插入的地方。
b.假如插入的值小於當前的值,而且當前左節點爲空,那麼左節點就指向新節點。
c.假如插入的值大於當前的值,而且當前右節點爲空,那麼右節點就指向新節點。this
public void insert(int id){ Node newNode = new Node(id); if(root == null){ root = newNode; return; } Node current = root; Node parent = null; while(true){ parent = current; if(id < current.data){ current = current.left; if(current == null){ parent.left = newNode; return; } } else { current = current.right; if(current == null){ parent.right = newNode; return; } } } }
3.二叉搜索樹的刪除
a.當刪除節點爲葉子節點時,直接刪除節點。
b.當刪除節點只有左子樹時,重接左子樹。
c.當刪除節點只有右子樹時,重接右子樹。
d.當刪除節點既有左子樹,又有右子樹時,先找一個能夠替換刪除節點的節點。因爲二叉樹的性質,左子樹的值小於根節點的值,右子樹的值大於根節點的值。因此右子樹的最左的節點就是替換刪除的節點,而後在重接右子樹。
第 d 點的圖例:spa
public boolean delete(int id) { Node parent = root; Node current = root; boolean isLeftChild = false; while (current.data != id) { parent = current; if (current.data > id) { isLeftChild = true; current = current.left; } else { isLeftChild = false; current = current.right; } if (current == null) { return false; } } //刪除的節點既沒左節點,也沒右節點 if (current.left == null && current.right == null) { if (current == root) { root = null; } if (isLeftChild == true) { parent.left = null; } else { parent.right = null; } } //刪除的節點只有左節點 else if (current.right == null) { if (current == root) { root = current.left; } else if (isLeftChild) { parent.left = current.left; } else { parent.right = current.left; } } //刪除的節點只有右節點 else if (current.left == null) { if (current == root) { root = current.right; } else if (isLeftChild) { parent.left = current.right; } else { parent.right = current.right; } } //刪除的節點既有左節點,又有右節點 else if (current.left != null && current.right != null) { //找到右子樹的最左節點 Node successor = getSuccessor(current); if (current == root) { root = successor; } else if (isLeftChild) { parent.left = successor; } else { parent.right = successor; } successor.left = current.left; } return true; } public Node getSuccessor(Node deleleNode) { Node successsor = null; Node successsorParent = null; Node current = deleleNode.right; while (current != null) { successsorParent = successsor; successsor = current; current = current.left; } if (successsor != deleleNode.right) { successsorParent.left = successsor.right; successsor.right = deleleNode.right; } return successsor; }
4.二叉搜索樹的查找code
public boolean find(int id) { Node current = root; while (current != null) { if (current.data == id) { return true; } else if (current.data > id) { current = current.left; } else { current = current.right; } } return false; }
因爲它是一顆有序的樹,就能夠進行折半查找,每一次查找,假如不是匹配的值,均可以排除一半的值。因此通常的時間複雜度是 O(log n)。假如這棵樹退化爲斜樹,就差很少是線性表了,它的時間複雜度就是 O(n)。排序
雖然二叉搜索樹的最壞時間複雜度是 O(n),但經過一些改進能夠把最壞時間複雜度降至 O(log n),好比 AVL樹、紅黑樹等。紅黑樹不須要絕對的平衡,因此插入和刪除效率上要高,在 JDK1.8 中哈希表存儲大於等於 8 個節點的鏈表就是採用的紅黑樹。rem
因此二叉搜索樹在查找上是很是快的,在一些須要很高查詢效率上推薦使用。get
PS:
清山綠水始於塵,博學多識貴於勤。
我有酒,你有故事嗎?
微信公衆號:「清塵閒聊」。
歡迎一塊兒談天說地,聊代碼。it