二叉樹的查詢演算法
阿新 • • 發佈:2019-01-25
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">二叉查詢樹</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">的基本演算法依賴的底層資料結構是二叉樹,該演算法實現的方法有:</span>
get()查詢
put()插入
min(),max()最小,最大值
ceiling(),floor()向上,向下取整
select(),rank()選擇,排序的方法
deleteMin(),deleteMax()刪除最小,最大值
delete()刪除指定的元素
keys()遍歷
public class BinarySearchTree<Key extends Comparable<Key>,Value> { private Node root; private class Node{ Key key; Value value; Node left,right; int N; public Node(Key key,Value value,int N){ this.key = key; this.value = value; this.N = N; } } //獲取當前二叉樹的節點個數 public int size(){ return size(root); } private int size(Node x){ if(x==null){ return 0; } return x.N; } //根據傳入的鍵,查詢並返回對應的值 public Value get(Key key){ return get(root,key); } private Value get(Node x,Key key){ if(x==null){ return null; } int tmp = key.compareTo(x.key); if(tmp<0){ return get(x.left,key); } if(tmp>0){ return get(x.right,key); } return x.value; } //插入節點,找到則更新,否則新建一個節點,並更新每個節點的計數器 public void put(Key key,Value value){ root = put(root,key,value); } private Node put(Node x,Key key,Value value){ if(x==null){ return new Node(key,value,1); } int tmp = key.compareTo(x.key); if(tmp<0){ x.left = put(x.left,key,value); } if(tmp>0){ x.right = put(x.right,key,value); } if(tmp==0){ x.value = value; } x.N = size(x.left)+size(x.right)+1; return x; } //min(),max()這兩種方法在二叉樹為空時會出現異常,因為該演算法在設計的時候就沒有考慮這個問題 public Key min(){ return min(root).key; } private Node min(Node x){//這裡只是找出節點 if(x.left!=null){ return min(x.left); } return x; } //找出最大的節點 public Key max(){ return max(root).key; } private Node max(Node x){ if(x.right!=null){ return max(x.right); } return x; } //找出大於等於該元素的最小元素,函式輸入該 元素的鍵,找出符合結果的鍵並返回 public Key ceiling(Key key){ Node t = ceiling(root,key); if(t==null){ return null; } return t.key; } private Node ceiling(Node x,Key key){ if(x==null){ return null; } int temp = key.compareTo(x.key); if(temp==0){ return x; } if(temp>0){ return ceiling(x.right,key); } Node t = ceiling(x.left,key); if(t==null){ return x;//這裡為什麼敢直接把x返回回去?因為至少有根節點是比要查詢的節點大的 }else{ return t; } } //找出小於等於該元素的最大元素,函式輸入該元素的鍵,找出符合結果的鍵並返回 public Key floor(Key key){ Node t = floor(root,key); if(t==null){ return null; } return t.key; } private Node floor(Node x,Key key){ if(x==null){ return null; } int temp = key.compareTo(x.key); if(temp==0){ return x; } if(temp<0){ return floor(x.left,key); } Node t = floor(x.right,key); if(t==null){ return x; }else{ return t; } } //函式輸入序列數值,函式返回二叉樹中排名為該序列數值的節點的鍵 public Key select(int n){ return select(root,n).key; } private Node select(Node x,int n){ if(x==null){ return null; } int tmp = size(x.left); if(n<tmp){ return select(x.left,n); } if(n>tmp){ return select(x.right,n-tmp-1); } return x; } //函式輸入鍵,在二叉樹中找到該鍵對應的序列數值,並返回 public int rank(Key key){ return rank(root,key); } private int rank(Node x,Key key){ if(x==null){ return 0; } int tmp = key.compareTo(x.key); if(tmp<0){ return rank(x.left,key); } if(tmp>0){ return 1+size(x.left)+rank(x.right,key); } return size(x.left); } //刪除最小元素 public void deleteMin(){ root = deleteMin(root); } private Node deleteMin(Node x){ if(x.left==null){ return x.right; } x.left = deleteMin(x.left); x.N = size(x.left) + size(x.right) + 1;//更新節點計數器 return x; } //刪除最大元素 public void deleteMax(){ root = deleteMax(root); } private Node deleteMax(Node x){ if(x.right==null){ return x.left; } x.right = deleteMax(x.right); x.N = size(x.left) + size(x.right) +1; return x; } // public void delete(Key key){ root = delete(root,key); } private Node delete(Node x,Key key){ if(x==null){ return null; } int tmp = key.compareTo(x.key); if(tmp<0){ x.left = delete(x.left,key); } if(tmp>0){ x.right = delete(x.right,key); } if(tmp==0){ if(x.left==null){ return x.right; }else if(x.right==null){ return x.left; } //這裡已經找到要刪除的元素了 Node t = x; x = min(t.right); x.left = t.left; x.right = deleteMin(t.right); } x.N = size(x.left)+size(x.right)+1; return x; } //查詢指定範圍的元素的方法 public Iterable<Key> keys(){ return keys(min(),max()); } private Iterable<Key> keys(Key lo,Key hi){ Queue<Key> queue = new Queue<Key>(); keys(queue,root,lo,hi); return queue; } private void keys(Queue<Key> queue,Node x,Key lo,Key hi){ if(x==null){ return; } int tmplo = lo.compareTo(x.key); int tmphi = hi.compareTo(x.key); if(tmplo<0){ keys(queue,x.left,lo,hi); } if(tmplo<=0 && tmphi>=0){ queue.enqueue(x.key); } if(tmphi>0){ keys(queue,x.right,lo,hi); } } }