一:概念
二叉搜索樹又稱二叉排序樹,它或者是一棵空樹**,或者是具備如下性質的二叉樹:
若它的左子樹不爲空,則左子樹上全部節點的值都小於根節點的值
若它的右子樹不爲空,則右子樹上全部節點的值都大於根節點的值
它的左右子樹也分別爲二叉搜索樹。
java
二:操做——查找
先和根節點作對比,相等返回,若是不相等,
關鍵碼key>根節點key,在右子樹中找(root=root.rightChild)
關鍵碼key<根節點key,在左子樹中找(root=root.leftChild)
不然返回falsenode
三:操做——插入
根據二叉排序樹的性質,左孩子比根節點的值小,右孩子比根節點的值大。關鍵碼key先於根節點key做比較,而後再判斷與根節點的左或者右做比較,知足二叉排序樹性質時,即爲合理位置,而後插入。ide
四: 操做-刪除(難點)
設待刪除結點爲 cur, 待刪除結點的雙親結點爲 parent
1. cur.left == null函數
五:實現性能
public class BinarySearchTree<K extends Comparable<K>, V> { public static class Node<K extends Comparable<K>, V> { K key; V value; Node<K, V> left; Node<K, V> right; public String toString() { return String.format("{%s, %s}", key, value); } } private Node<K, V> root = null; public V get(K key) { Node<K, V> parent = null; Node<K, V> cur = root; while (cur != null) { parent = cur; int r = key.compareTo(cur.key); if (r == 0) { return cur.value; } else if (r < 0) { cur = cur.left; }
else { cur = cur.right; } } return null; } public V put(K key, V value)
{ if (root == null) { root = new Node<>(); root.key = key; root.v display(root); return null; } Node<K, V> parent = null; Node<K, V> cur = root; while (cur != null) { parent = cur;
int r = key.compareTo(cur.key); if (r == 0) { V oldValue = cur.value; cur.value = value; display(root); return oldValue; } else if (r < 0) { cur = cur.left; } else
{ cur = cur.right; } } Node<K, V> node = new Node<>(); node.key = key; node.value = value; int r = key.compareTo(parent.key); if (r < 0) { parent.left = node; } else { parent.right = node; } display(root); return null; } public V remove(K key) {
Node<K, V> parent = null; Node<K, V> cur = root; while (cur != null) { int r = key.compareTo(cur.key); if (r == 0) { V oldValue = cur.value; deleteNode(parent, cur); display(root); return oldValue; } else if (r < 0) { parent = cur; cur = cur.left; } else { parent = cur; cur = cur.right; } } display(root); return null; } private void deleteNode(Node<K,V> parent, Node<K,V> cur) { if (cur.left == null) { if (cur == root) { root = cur.right; } else if (cur == parent.left) { parent.left = cur.right; } else { parent.right = cur.right; } } else if (cur.right == null) { if (cur == root) { root = cur.left; } else if (cur == parent.left) { parent.left = cur.left; } else { parent.right = cur.left; } } else { // 去 cur 的右子樹中尋找最小的 key 所在的結點 scapegoat // 即 scapegoat.left == null 的結點 Node<K,V> goatParent = cur; Node<K,V> scapegoat = cur.right; while (scapegoat.left != null) { goatParent = scapegoat; scapegoat = cur.left; } cur.key = scapegoat.key; cur.value = scapegoat.value; if (scapegoat == goatParent.left) { goatParent.left = scapegoat.right; } else { goatParent.right = scapegoat.right; } } } private static <K extends Comparable<K>,V> void display(Node<K,V> node) { System.out.print("前序: "); preOrder(node);
System.out.println(); System.out.print("中序: ") inOrder(node); System.out.println(); } private static <K extends Comparable<K>,V> void preOrder(Node<K,V> node) { if (node == null) { return; } System.out.print(node + " "); preOrder(node.left); preOrder(node.right); } private static <K extends Comparable<K>,V> void inOrder(Node<K,V> node) { if (node == null) { return; } inOrder(node.left); System.out.print(node + " "); inOrder(node.right); } public static void main(String[] args) { BinarySearchTree<Integer, String> tree = new BinarySearchTree<>(); int[] keys = { 5, 3, 7, 4, 2, 6, 1, 9, 8 }; for (int key : keys) { tree.put(key, String.valueOf(key)); } System.out.println("=================================="); tree.put(3, "修改過的 3"); System.out.println("=================================="); tree.remove(9); tree.remove(1); t ree.remove(3); ``` } }
**六:性能分析** 插入和刪除操做都必須先查找,查找效率表明了二叉搜索樹中各個操做的性能。 對有n個結點的二叉搜索樹,若每一個元素查找的機率相等,則二叉搜索樹平均查找長度是結點在二叉搜索樹的深度的函數,即結點越深,則比較次數越多。 但對於同一個關鍵碼集合,若是各關鍵碼插入的次序不一樣,可能獲得不一樣結構的二叉搜索樹。 **七: 和 java 類集的關係** TreeMap 和 TreeSet 即 java 中利用搜索樹實現的 Map 和 Set;