一、采用存儲結構
1、順序存儲:采用數組,順序存儲適配於完全二叉樹,對於非完全二叉樹並不合適,主要體現在空間上的浪費,所以我們需要用到另一種存儲方式——鏈式存儲。
2、鏈式存儲:數據data用鍵值對的形式表示
二、建立二叉樹
//自己建一個Node類,樹有Node對象組成 private class Node{ private Key key; //鍵 private Value val; //值 private Node left,right; //左右子樹 private int N; //結點計數器 public Node(Key key,Value val,int N) { this.key = key; this.val = val; this.N = N; } } 變量N給出了以該節點為根的子樹的結點總數
三、二叉查找樹的查、插、刪、遍歷
package BSTree; public class BST_1 <Key extends Comparable<Key>,Value>{ private Node root;//二叉查找樹的根 private class Node{ private Key key; private Value value; private Node lchild,rchild; private int N; //以該節點為根的子樹中的結點個數 //構造方法 public Node(Key key,Value value,int N) { this.key = key; this.value =value; this.N = N; } @Override public String toString() { return "Node [key=" + key + ", value=" + value + ", N=" + N + "]"; } } //獲取節點個數N public int size() { return size(root); } private int size(Node x) { if(x==null) return 0; return x.N; } //通過Key查找Value public Value search(Key key) { return search(root,key); } private Value search(Node x,Key key) { //找不到,返回null if(x==null) return null; //如果不為空,用待查找的值與當前根節點的值進行比較 int result = key.compareTo(x.key);//返回一個整數,大於或小於或等於0 if(result>0) return search(x.rchild, key);//大於,往右子樹遞歸查 else if(result<0) return search(x.lchild, key); else return x.value; } //插入 public void insert(Key key,Value value){ root = insert(root,key,value); } private Node insert(Node x, Key key, Value value) { //如果key已經存在,則修改value為新的value值,不存在,則創建一個新的結點 if(x==null) return new Node(key, value, 1); int result = key.compareTo(x.key); if(result>0) x.rchild = insert(x.rchild, key, value); else if(result<0) x.lchild = insert(x.lchild, key, value); else x.value = value; x.N = size(x.rchild)+size(x.rchild)+1; return x; } //查找最小鍵 public Key min() { return min(root).key; } private Node min(Node x) { if(x.lchild==null) return x; else return min(x.lchild); } //二叉查找樹中最難的就是刪除,先從刪最簡單的最小結點開始 public void deleteMin() { root = deleteMin(root); } //返回已經刪了最小結點的根節點 private Node deleteMin(Node x) { //在找到最小結點時x時,x=x.right if(x.lchild==null) return x.rchild; x.lchild = deleteMin(x.lchild); x.N = size(x.rchild)+size(x.rchild)+1; return x; } /**刪除任意節點 * 1.如果樹為null或者找不到key,返回null * 2.否則,通過比較找到鍵Key的結點: * 如果該結點沒有右子樹 ,只有左子樹 x = x.left * 如果該結點沒有左子樹 ,只有有子樹x = x.right * 該結點左右子樹都有,先用Node t = x 存x結點, * 找到以t.right為根節點的樹的最小鍵, 賦予x: x = min(x.right),及替換x結點 * 然后把這個最小鍵刪了,把t結點的左子樹賦予x.left * 3.返回 返回已經刪了結點的根節點 * */ public void delete(Key key) { root = delete(root,key); } private Node delete(Node x, Key key) { if(x==null) return null; int result = key.compareTo(x.key); if(result>0) x.rchild = delete(x.rchild, key); else if(result<0) x.lchild = delete(x.lchild, key); else { if(x.rchild==null) return x.lchild; if(x.lchild==null) return x.rchild; Node t = x; x = min(t.rchild); x.rchild = deleteMin(t.rchild); x.lchild = t.lchild; } x.N = size(x.lchild)+size(x.rchild)+1; return x; } //前序遍歷:根--左子樹--右子樹 public void preOrder() { preOrder(root); } private void preOrder(Node x) { if(x!=null) { System.out.print("["+x.key+":"+x.value+"]"+" "); preOrder(x.lchild); preOrder(x.rchild); } } //中序遍歷:左子樹--根節點--右子樹 public void inOrder() { inOrder(root); } private void inOrder(Node x) { if(x!=null) { inOrder(x.lchild); System.out.print("["+x.key+":"+x.value+"]"+" "); inOrder(x.rchild); } } //后序遍歷:左子樹--右子樹--根節點 public void postOrder() { postOrder(root); } private void postOrder(Node x) { if(x!=null) { postOrder(x.lchild); postOrder(x.rchild); System.out.print("["+x.key+":"+x.value+"]"+" "); } } }