生活随笔
收集整理的這篇文章主要介紹了
数据结构与算法--二叉查找树实现原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
二叉查找樹
- 二叉樹的一個重要應用就是他在查詢中的使用,假設書中每個節點存儲一項數據。在我們的案例中,任意復雜的項在java中都容易處理,但為了簡單還是假設都是整數。還假設他們都是不重復的整數,使二叉樹稱為二叉查找樹的性質是:
- 對于樹中每個節點X,左子樹中所有項小于X中的項
- 而右子樹中的所有元素都大于X中的項目
- 依據以上規則,意味著改樹中所有元素都可以用某種一致的方式排序。
- 如上圖中圖一中的樹是二叉查找樹,但是圖二中的樹不是,圖二中樹在其項是3 的節點的右子樹 上 有一個節點項是1 ,1< 3,右子節點中數據有小于該節點數據的項目,違反的二叉樹的兩個規則之一。
二叉查找樹的實現
- 二叉查找樹要求所有項都能夠排序,那么必定在樹中任意兩個節點之間都可以進行比較,所以我們必須對樹節點實現Comparable接口。節點定義如下,和上篇中定義有一點不同:
public class BinaryNode implements Comparable {private Object element
;private BinaryNode left
;private BinaryNode right
;private int count
;public BinaryNode(Object element
, BinaryNode left
, BinaryNode right
) {this.element
= element
;this.left
= left
;this.right
= right
;this.count
= 1;}public Object
getElement() {return element
;}public void setElement(Object element
) {this.element
= element
;}public BinaryNode
getLeft() {return left
;}public void setLeft(BinaryNode left
) {this.left
= left
;}public BinaryNode
getRight() {return right
;}public void setRight(BinaryNode right
) {this.right
= right
;}public int getCount() {return count
;}public void setCount(int count
) {this.count
= count
;}@Overridepublic int compareTo(Object o
) {if(o
== null
){return 1;}int flag
= this.element
.toString().compareTo(o
.toString());if(flag
== 0){return 0;}else if (flag
> 0){return 1;}else {return -1;}}
}
public class BinarySearchTree {public void makeEmpty(BinaryNode root
) {root
= null
;}public boolean isEmpty(BinaryNode root
) {return root
== null
;}private boolean contains(Object x
, BinaryNode t
) {if (x
== null
) {return false;}if (t
== null
) {return false;}int flag
= t
.compareTo(x
);if (flag
> 0) {return contains(x
, t
.getLeft());} else if (flag
< 0) {return contains(x
, t
.getRight());} else {return true;}}private BinaryNode
findMin(BinaryNode t
) {if (t
== null
) {return null
;}if (t
.getLeft() != null
) {return findMin(t
.getLeft());}return t
;}private BinaryNode
findMax(BinaryNode t
) {if (t
== null
) {return null
;}if (t
.getRight() != null
) {return findMax(t
.getRight());}return t
;}private BinaryNode
insert(Object x
, BinaryNode t
) {if (x
== null
) {return t
;}if (t
== null
|| t
.getElement() == null
) {t
= new BinaryNode(x
, null
, null
);return t
;}int flag
= t
.compareTo(x
);if (flag
> 0) {t
.setLeft(insert(x
, t
.getLeft()));} else if (flag
< 0) {t
.setRight(insert(x
, t
.getRight()));} else {t
.setCount(t
.getCount() + 1);}return t
;}private BinaryNode
remove(Object x
, BinaryNode t
) {if (x
== null
) {return t
;}int flag
= t
.compareTo(x
);if (flag
> 0) {return remove(x
, t
.getLeft());} else if (flag
< 0) {return remove(x
, t
.getRight());} else if (t
.getLeft() != null
&& t
.getRight() != null
) {BinaryNode min
= findMin(t
.getRight());t
.setElement(min
.getElement());remove(min
.getElement(), t
.getRight());} else {t
= t
.getLeft() != null
? t
.getLeft() : t
.getRight();}return t
;}public void printTree(BinaryNode t
) {if (t
== null
|| t
.getElement() == null
) {return;}printTree(t
.getLeft());for (int i
= 0; i
< t
.getCount(); i
++) {System
.out
.print(t
.getElement() + " ");}printTree(t
.getRight());}public static void main(String
[] args
) {BinaryNode node
= new BinaryNode(null
, null
, null
);BinarySearchTree searchTree
= new BinarySearchTree();Random random
= new Random();for (int i
= 0; i
< 20; i
++) {node
= searchTree
.insert(random
.nextInt(1000), node
);}System
.out
.println(searchTree
.findMax(node
).getElement());System
.out
.println(searchTree
.findMin(node
).getElement());searchTree
.printTree(node
);if(!searchTree
.contains(13, node
)){node
= searchTree
.insert(13, node
);}System
.out
.println(searchTree
.contains(13, node
));node
= searchTree
.remove(13, node
);System
.out
.println(searchTree
.contains(13, node
));}
}
方法解析:
containes方法
- 如果在樹T中包含有項目X的節點,你們這個需要返回True,否則放回false。我們用兩個遞歸調用來實現這個方法,其實也可以用while循環來替代遞歸調用。但是這里用遞歸也是合理的,因為算法表達式的簡單性是以降低速度為代價的,而這里所使用的棧空間的量也不過是O(logN)而已
findMin,findMax方法
- 同樣遞歸,依據二叉查找樹的規則左子樹永遠小于本節點,所以一直向左節點遞歸 可以得到最小值,同樣,一直向右節點遞歸可以得到最大值
insert方法
- 插入操作概念是簡單的。為了將X插入到樹T中,可以用contains方法那樣沿著樹查找。如果找到X,則更新數量。否則將X插入到變量的路徑上的最后一個點上。如下圖顯示,為了插入4, 我們遍歷改樹就好像在運行contains。在具有關鍵字的1節點處我們需要向右邊行進,但是右邊不存在子樹,因此4不在這棵樹上,從而這個位置就是我們要插入的位置,將4節點的引用交給 1 節點的right
- 重復插入可以在節點距離中保留一個附加字段頻率來處理,就想我們定義的count
remove方法
平均時間復雜度分析
- 二叉樹我們期望的平均時間復雜度是O(logN)時間,但是一顆二叉查找樹在不斷的insert和remove的過程中,由于上面我們所采用的的刪除策略有助于使得左子樹的深度比右子樹更深,因為我們總是用右子樹中最小的節點去替換需要刪除的節點。這種方案的準確性是已經在業界證明可行,就避免不了最終不平衡的可能。
- 我們在刪除過程中可以通過隨機選取右子樹的最小元素 和 左子樹的最大元素來代替刪除元素的策略來消除這種不平衡問題,但是這種做法還沒有人能證明可行性。
- 好像不能完全解決平衡問題,出發我們增加一個平衡(balance)的附加條件:任何節點深度不得過深那就是AVL樹。
上一篇:數據結構與算法–重建二叉樹
下一篇:數據結構與算法–AVL樹原理及實現
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的数据结构与算法--二叉查找树实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。