1. 程式人生 > >JAVA數據結構--二叉查找樹

JAVA數據結構--二叉查找樹

true 暫時 技術 單個 二叉 compare opened 鍵值 extends

二叉查找樹定義

二叉查找樹英語:Binary Search Tree),也稱二叉搜索樹、有序二叉樹(英語:ordered binary tree),排序二叉樹(英語:sorted binary tree),是指一棵空樹或者具有下列性質的二叉樹:

  1. 若任意節點的左子樹不空,則左子樹上所有節點的值均小於它的根節點的值;
  2. 若任意節點的右子樹不空,則右子樹上所有節點的值均大於它的根節點的值;
  3. 任意節點的左、右子樹也分別為二叉查找樹;
  4. 沒有鍵值相等的節點。

二叉查找樹相比於其他數據結構的優勢在於查找、插入的時間復雜度較低。為O(log n)。

技術分享圖片三層二叉查找樹

二叉查找樹的操作主要是運用的遞歸的思想,可操作的Object類必須繼承了Comparable接口,個人實現查找樹主要是參考了《數據結構與算法分析》這本書。因為遍歷涉及到三種遍歷方式,所以屆時單獨開一篇。

樹的結點定義

 1 private static class BinaryNode<T>{
 2         BinaryNode(T theElement) {
 3             this(theElement,null,null);
 4         }
 5         BinaryNode(T theElement,BinaryNode<T> lt,BinaryNode<T> rt) {
 6             element=theElement;
 7             left=lt;
 8             right=rt;
9 } 10 T element;//根節點 11 BinaryNode<T> left;//左子樹 12 BinaryNode<T> right;//右子樹 13 }

contains方法

 1 private boolean contains(T x,BinaryNode<T> t){
 2         if(t==null)
 3             return false;
 4         int compareResult=x.compareTo(t.element);
5 if(compareResult<0) 6 return contains(x,t.left); //遞歸 7 else if (compareResult>0) { 8 return contains(x, t.right); 9 } 10 else { 11 return true; 12 } 13 }

contains方法主要是查找當前二叉樹是否還有某個節點,利用了comparaTo方法遞歸調用。

findMin()與findMax()方法

 1 private BinaryNode<T> findMin(BinaryNode<T> t){
 2         //非遞歸寫法
 3         if(t!=null)
 4             while(t.left!=null)
 5                 t=t.left;
 6         return t;
 7         //遞歸寫法
 8         /*if(t==null)
 9             return null;
10         else if (t.left==null) {
11             return t;
12         }
13         return findMin(t.left);*/
14     }

findMin與findMax方法類似,這裏只列出一種即可。然後仍有兩種方法解決此問題,一種為遞歸,一種非遞歸。

非遞歸方法就是采用了while循壞思想,直到找出最左的節點即可

insert方法

 1 private BinaryNode<T> insert(T x,BinaryNode<T> t){
 2         if(t==null)//生成新的節點
 3             return new BinaryNode<T>(x, null, null);
 4         if(contains(x))//如果二叉樹中已經有x元素,則不進行任何操作
 5             return t;
 6         else {
 7             int compareResult=x.compareTo(root.element);
 8             if(compareResult<0){
 9                 t.left=insert(x, t.left);
10             }
11             else {
12                 t.right=insert(x, t.right);
13             }
14             return t;
15         }
16     }

remove方法

 1 private BinaryNode<T> remove(T x,BinaryNode<T> t){
 2         if(t==null)
 3             return t;
 4         int compareResult=x.compareTo(t.element);
 5         if(compareResult<0){
 6             t.left=remove(x, t.left);
 7         }
 8         else if(compareResult>0){
 9             t.right=remove(x, t.right);
10         }
11         else if (t.left!=null&&t.right!=null) {    //兩個孩子情況,采取懶惰刪除
12             t.element=findMin(t.right).element;
13             t.right=remove(t.element, t.right);
14         }
15         else {    //單個孩子情況
16             t=(t.left!=null)?t.left:t.right;
17         }
18         return t;
19     }

刪除節點時需要考慮兩種情況,一種為兩個孩子的情況,一種為單個孩子的情況。

技術分享圖片如圖為刪除5節點為單個孩子情況

技術分享圖片此圖是刪除3節點兩個孩子的情況,具體做法是找出該節點右子樹中最小的節點替換當前刪除的節點

全部的代碼如下(暫缺遍歷)

技術分享圖片
  1 package Tree;
  2 
  3 public class BinarySearchTree<T extends Comparable<? super T>> {
  4     private static class BinaryNode<T>{
  5         BinaryNode(T theElement) {
  6             this(theElement,null,null);
  7         }
  8         BinaryNode(T theElement,BinaryNode<T> lt,BinaryNode<T> rt) {
  9             element=theElement;
 10             left=lt;
 11             right=rt;
 12         }
 13         T element;//根節點
 14         BinaryNode<T> left;//左子樹
 15         BinaryNode<T> right;//右子樹
 16     }
 17     private BinaryNode<T> root;//定義根節點
 18     public BinarySearchTree() {
 19         root=null;
 20     }
 21     public void makeEmpty(){
 22         root=null;
 23     }
 24     public boolean isEmpty(){
 25         return root==null;
 26     }
 27     public boolean contains(T x){
 28         return contains(x,root);
 29     }
 30     public T findMin() throws Exception{
 31         if(isEmpty())
 32             throw new Exception();
 33         return findMin(root).element;
 34     }
 35     public T findMax() throws Exception{
 36         if(isEmpty())
 37             throw new Exception();
 38         return findMax(root).element;
 39     }
 40     public void insert(T x){
 41         root=insert(x,root);
 42     }
 43     public void remove(T x){
 44         root=remove(x,root);
 45     }
 46     private boolean contains(T x,BinaryNode<T> t){
 47         if(t==null)
 48             return false;
 49         int compareResult=x.compareTo(t.element);
 50         if(compareResult<0)
 51             return contains(x,t.left);    //遞歸
 52         else if (compareResult>0) {
 53             return contains(x, t.right);
 54         }
 55         else {
 56             return true;
 57         }
 58     }
 59     private BinaryNode<T> findMin(BinaryNode<T> t){
 60         //非遞歸寫法
 61         if(t!=null)
 62             while(t.left!=null)
 63                 t=t.left;
 64         return t;
 65         //遞歸寫法
 66         /*if(t==null)
 67             return null;
 68         else if (t.left==null) {
 69             return t;
 70         }
 71         return findMin(t.left);*/
 72     }
 73     private BinaryNode<T> findMax(BinaryNode<T> t){
 74         if(t!=null)
 75             while(t.right!=null)
 76                 t=t.right;
 77         return t;
 78     }
 79     private BinaryNode<T> insert(T x,BinaryNode<T> t){
 80         if(t==null)//生成新的節點
 81             return new BinaryNode<T>(x, null, null);
 82         if(contains(x))//如果二叉樹中已經有x元素,則不進行任何操作
 83             return t;
 84         else {
 85             int compareResult=x.compareTo(root.element);
 86             if(compareResult<0){
 87                 t.left=insert(x, t.left);
 88             }
 89             else {
 90                 t.right=insert(x, t.right);
 91             }
 92             return t;
 93         }
 94     }
 95     private BinaryNode<T> remove(T x,BinaryNode<T> t){
 96         if(t==null)
 97             return t;
 98         int compareResult=x.compareTo(t.element);
 99         if(compareResult<0){
100             t.left=remove(x, t.left);
101         }
102         else if(compareResult>0){
103             t.right=remove(x, t.right);
104         }
105         else if (t.left!=null&&t.right!=null) {    //兩個孩子情況,采取懶惰刪除
106             t.element=findMin(t.right).element;
107             t.right=remove(t.element, t.right);
108         }
109         else {    //單個孩子情況
110             t=(t.left!=null)?t.left:t.right;
111         }
112         return t;
113     }
114 
115 }
View Code

也可訪問我的gihub數據結構的部分,暫時內容較少。

JAVA數據結構--二叉查找樹