二叉查找樹的創建
1:二叉樹的結點類:
代碼實現如下:
private class Node{
//存儲鍵
private Key key;
//存儲值
public Value vlaue;
//記錄左子結點
public Node left;
//記錄右子結點
public Node right;
//構造函數
public Node(Key key,Value value,Node left,Node right){
this.key = key;
this.vlaue = value;
this.left = left;
this.right = right;
}
}
2:二叉查找樹API設計:
public void put(Key key,Value value):向樹中添加元素key–value
private Node put(Node x,Key key,Value value):向指定的樹x中添加key-vlaue,並返回添加元素後新的樹
----------------插入方法put實現思想:
1.如果當前樹中沒有任何一個結點,則直接把新結點當做根結點使用;
2:如果當前樹不爲空,則從根結點開始:
··········2.1:如果新結點的key小於當前結點的key,則繼續查找當前結點的左子結點;
··········2.2:如果新結點的key大於當前結點的key,則繼續查找當前結點的右子結點;
··········2.3:如果新結點的key等於當前結點的key,則樹中已經存在這樣的結點,替換該結點的value值即可;
代碼實現入下:
//向樹中添加元素key--value
public void put(Key key,Value value){
root = put(root,key,value);
}
//向指定的樹x中添加key-vlaue,並返回添加元素後新的樹
private Node put(Node x,Key key,Value value){
//如果x子樹爲空
if(x == null){
N++;
return new Node(key,value,null,null);
}
//如果x子樹不爲空
//比較x結點的鍵和key的大小
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大於x結點的鍵,則繼續找x結點的右子樹
x.right = put(x.right,key,value);
}else if(cmp < 0){
//如果key小於x結點的鍵,則繼續找x結點的左子樹
x.left = put(x.left,key,value);
}else {
//如果key等於x結點的鍵,則替換x結點的值爲value
x.vlaue = value;
}
return x;
}
public Value get(Key key):查詢樹中指定key對應的value
public Value get(Node x,Key key):從指定的樹x中,查找key對應的值
----------------查找方法get實現思想:
從根節點開始:
·········1:如果要查詢的key小於當前結點的key,則繼續查找當前結點的左子結點;
·········2:如果要查詢的key大於當前結點的key,則繼續查找當前結點的右子結點;
·········3:如果要查詢的Key等於當前結點的key,則樹中返回當前結點的value;
代碼實現入下:
//查詢樹中指定key對應的value
public Value get(Key key){
return get(root,key);
}
//從指定的樹x中,查找key對應的值
public Value get(Node x,Key key){
//x樹爲Null
if(x == null){
return null;
}
//x樹不爲null
//比較key和x結點的鍵的大小
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大於x結點的鍵,則繼續找x結點的右子樹
return get(x.right,key);
}else if(cmp < 0){
//如果key小於x結點的鍵,則繼續找x結點的左子樹
return get(x.left,key);
}else {
//如果key等於x結點的鍵,則替換x結點的值爲value
return x.vlaue;
}
}
public void delete(Key key):刪除樹中key對應的value
public Node delete(Node x,Key key):刪除指定樹x中的key對應的value,並返回刪除後的新樹
----------------刪除方法delete實現思想:
1:找到被刪除的結點;
2:找到被刪除結點右子樹中的最小結點minNode;
3:刪除右子樹中的最小結點;
4:讓被刪除結點的左子樹稱爲最小結點minNode的左子樹,讓被刪除結點的右子樹成爲最小結點minNode的右子樹;
5:讓被刪除結點的父節點指向最小結點minNode;
代碼實現入下:
//刪除樹中key對應的value
public void delete(Key key){
delete(root,key);
}
//刪除指定樹x中的key對應的value,並返回刪除後的新樹
public Node delete(Node x,Key key){
//x樹爲null
if(x == null){
return null;
}
//x樹不爲null
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大於x結點的鍵,則繼續找x結點的右子樹
x.right = delete(x.right,key);
}else if(cmp < 0){
//如果key小於x結點的鍵,則繼續找x結點的左子樹
x.left = delete(x.left,key);
}else {
//如果key等於x結點的鍵,完成真正的刪除結點動作,要刪除的結點就是x
//讓元素個數-1
N--;
//得找到右子樹中最小得結點
if(x.right == null){
return x.left;
}
if(x.left == null){
return x.right;
}
Node minNode = x.right;
while (minNode.left != null){
minNode = minNode.left;
}
//刪除右子樹中最小得結點
Node n = x.right;
while (n.left != null){
if(n.left.left == null){
n.left = null;
}else {
//變換n結點即可
n = n.left;
}
}
//讓x結點得左子樹成爲minNode的左子樹
minNode.left = x.left;
//讓x結點的右子樹成爲minNode的右子樹
minNode.right = x.right;
//讓x結點的父結點指向minNode
x = minNode;
}
return x;
}
下面爲完整代碼(附帶檢測):
public class BinaryTree<Key extends Comparable<Key>,Value> {
//記錄根節點
private Node root;
//記錄樹中元素的個數
private int N;
private class Node{
//存儲鍵
private Key key;
//存儲值
public Value vlaue;
//記錄左子結點
public Node left;
//記錄右子結點
public Node right;
//構造函數
public Node(Key key,Value value,Node left,Node right){
this.key = key;
this.vlaue = value;
this.left = left;
this.right = right;
}
}
//獲取樹中元素的個數
public int size(){
return N;
}
//向樹中添加元素key--value
public void put(Key key,Value value){
root = put(root,key,value);
}
//向指定的樹x中添加key-vlaue,並返回添加元素後新的樹
private Node put(Node x,Key key,Value value){
//如果x子樹爲空
if(x == null){
N++;
return new Node(key,value,null,null);
}
//如果x子樹不爲空
//比較x結點的鍵和key的大小
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大於x結點的鍵,則繼續找x結點的右子樹
x.right = put(x.right,key,value);
}else if(cmp < 0){
//如果key小於x結點的鍵,則繼續找x結點的左子樹
x.left = put(x.left,key,value);
}else {
//如果key等於x結點的鍵,則替換x結點的值爲value
x.vlaue = value;
}
return x;
}
//查詢樹中指定key對應的value
public Value get(Key key){
return get(root,key);
}
//從指定的樹x中,查找key對應的值
public Value get(Node x,Key key){
//x樹爲Null
if(x == null){
return null;
}
//x樹不爲null
//比較key和x結點的鍵的大小
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大於x結點的鍵,則繼續找x結點的右子樹
return get(x.right,key);
}else if(cmp < 0){
//如果key小於x結點的鍵,則繼續找x結點的左子樹
return get(x.left,key);
}else {
//如果key等於x結點的鍵,則替換x結點的值爲value
return x.vlaue;
}
}
//刪除樹中key對應的value
public void delete(Key key){
delete(root,key);
}
//刪除指定樹x中的key對應的value,並返回刪除後的新樹
public Node delete(Node x,Key key){
//x樹爲null
if(x == null){
return null;
}
//x樹不爲null
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大於x結點的鍵,則繼續找x結點的右子樹
x.right = delete(x.right,key);
}else if(cmp < 0){
//如果key小於x結點的鍵,則繼續找x結點的左子樹
x.left = delete(x.left,key);
}else {
//如果key等於x結點的鍵,完成真正的刪除結點動作,要刪除的結點就是x
//讓元素個數-1
N--;
//得找到右子樹中最小得結點
if(x.right == null){
return x.left;
}
if(x.left == null){
return x.right;
}
Node minNode = x.right;
while (minNode.left != null){
minNode = minNode.left;
}
//刪除右子樹中最小得結點
Node n = x.right;
while (n.left != null){
if(n.left.left == null){
n.left = null;
}else {
//變換n結點即可
n = n.left;
}
}
//讓x結點得左子樹成爲minNode的左子樹
minNode.left = x.left;
//讓x結點的右子樹成爲minNode的右子樹
minNode.right = x.right;
//讓x結點的父結點指向minNode
x = minNode;
}
return x;
}
}
//主程序
public class TestBinaryTree {
public static void main(String[] args) {
//創建二叉查找樹對象
BinaryTree<Integer, String> tree = new BinaryTree<>();
//測試插入
tree.put(3,"張三");
tree.put(2,"李四");
tree.put(1,"王五");
tree.put(4,"趙六");
tree.put(5,"楊七");
System.out.println("插入完畢後元素的個數:"+tree.size());
//測試獲取
System.out.println("鍵5對應的元素是:"+tree.get(5));//楊七
//測試刪除
tree.delete(2);
System.out.println("刪除後的元素個數:"+tree.size());
System.out.println("刪除後鍵2對應的元素;"+tree.get(2));
}
}