TreeMap和TreeSet即Java中利用二叉搜索樹實現的Map和Set

一:概念
二叉搜索樹又稱二叉排序樹,它或者是一棵空樹**,或者是具備如下性質的二叉樹:
若它的左子樹不爲空,則左子樹上全部節點的值都小於根節點的值
若它的右子樹不爲空,則右子樹上全部節點的值都大於根節點的值
它的左右子樹也分別爲二叉搜索樹。
TreeMap和TreeSet即Java中利用二叉搜索樹實現的Map和Setjava

二:操做——查找
先和根節點作對比,相等返回,若是不相等,
關鍵碼key>根節點key,在右子樹中找(root=root.rightChild)
關鍵碼key<根節點key,在左子樹中找(root=root.leftChild)
不然返回falsenode

三:操做——插入
根據二叉排序樹的性質,左孩子比根節點的值小,右孩子比根節點的值大。關鍵碼key先於根節點key做比較,而後再判斷與根節點的左或者右做比較,知足二叉排序樹性質時,即爲合理位置,而後插入。ide

四: 操做-刪除(難點)
設待刪除結點爲 cur, 待刪除結點的雙親結點爲 parent
1. cur.left == null函數

  1. cur 是 root,則 root = cur.right
  2. cur 不是 root,cur 是 parent.left,則 parent.left = cur.right
  3. cur 不是 root,cur 是 parent.right,則 parent.right = cur.right
    2. cur.right == null
  4. cur 是 root,則 root = cur.left
  5. cur 不是 root,cur 是 parent.left,則 parent.left = cur.left
  6. cur 不是 root,cur 是 parent.right,則 parent.right = cur.left
    3. cur.left != null && cur.right != null
  7. 須要使用替換法進行刪除,即在它的右子樹中尋找中序下的第一個結點(關鍵碼最小),用它的值填補到被刪除節點中,再來處理該結點的刪除問題

五:實現性能

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;
相關文章
相關標籤/搜索