排序二叉树BST(binary search/sort tree)
之前介紹說(shuō),樹這種存儲(chǔ)結(jié)構(gòu),能提高數(shù)據(jù)的存儲(chǔ),讀取效率。所以樹的應(yīng)用就可以體現(xiàn)在排序這一方面,比如有排序二叉樹,平衡二叉樹,紅黑樹等。本文介紹排序二叉樹。
為啥有排序二叉樹(二叉搜索樹)的出現(xiàn)?這要從二分查找算法說(shuō)起:
排序二叉樹:
BST樹的搜索
BST樹的搜索,從根結(jié)點(diǎn)開始,如果查詢的關(guān)鍵字與結(jié)點(diǎn)的關(guān)鍵字相等,那么就命中;否則,如果查詢關(guān)鍵字比結(jié)點(diǎn)關(guān)鍵字小,就進(jìn)入左子節(jié)點(diǎn);如果比結(jié)點(diǎn)關(guān)鍵字大,就進(jìn)入右子節(jié)點(diǎn);如果左子節(jié)點(diǎn)或右子節(jié)點(diǎn)的指針為空,則報(bào)告找不到相應(yīng)的關(guān)鍵字;如果BST樹的所有非葉子結(jié)點(diǎn)的左右子樹的結(jié)點(diǎn)數(shù)目均保持差不多(平衡),那么B樹的搜索性能逼近二分查找;但它比連續(xù)內(nèi)存空間的二分查找的優(yōu)點(diǎn)是,改變BST樹結(jié)構(gòu)(比如插入與刪除結(jié)點(diǎn))無(wú)需移動(dòng)大段的內(nèi)存數(shù)據(jù),甚至通常是常數(shù)開銷。
如上圖:右邊也是一個(gè)BST樹,但它的搜索性能已經(jīng)是線性的了;同樣的關(guān)鍵字集合有可能導(dǎo)致不同的樹結(jié)構(gòu)索引;所以,使用BST樹還要考慮盡可能讓BST樹保持左圖的結(jié)構(gòu),和避免右圖的結(jié)構(gòu),也就是所謂的“平衡”問(wèn)題;解決方案就是平衡二叉樹了。
BST的創(chuàng)建
創(chuàng)建排序二叉樹的步驟,也就是不斷地向排序二叉樹添加節(jié)點(diǎn)的過(guò)程,向排序二叉樹添加節(jié)點(diǎn)的步驟如下:
以根節(jié)點(diǎn)當(dāng)前節(jié)點(diǎn)開始搜索。
拿新節(jié)點(diǎn)的值和當(dāng)前節(jié)點(diǎn)的值比較。
如果新節(jié)點(diǎn)的值更大,則以當(dāng)前節(jié)點(diǎn)的右子節(jié)點(diǎn)作為新的當(dāng)前節(jié)點(diǎn);如果新節(jié)點(diǎn)的值更小,則以當(dāng)前節(jié)點(diǎn)的左子節(jié)點(diǎn)作為新的當(dāng)前節(jié)點(diǎn)。
重復(fù) 2、3 兩個(gè)步驟,直到搜索到合適的葉子節(jié)點(diǎn)為止。
將新節(jié)點(diǎn)添加為第 4 步找到的葉子節(jié)點(diǎn)的子節(jié)點(diǎn);如果新節(jié)點(diǎn)更大,則添加為右子節(jié)點(diǎn);否則添加為左子節(jié)點(diǎn)。
BST刪除節(jié)點(diǎn)
當(dāng)程序從排序二叉樹中刪除一個(gè)節(jié)點(diǎn)之后,為了讓它依然保持為排序二叉樹,程序必須對(duì)該排序二叉樹進(jìn)行維護(hù)。維護(hù)可分為如下幾種情況:
- (1)被刪除的節(jié)點(diǎn)是葉子節(jié)點(diǎn),則只需將它從其父節(jié)點(diǎn)中刪除即可。
- (2)被刪除節(jié)點(diǎn) p 只有左子樹,將 p 的左子樹 添加成 p 的父節(jié)點(diǎn)的左子樹即可;被刪除節(jié)點(diǎn) p 只有右子樹,將 p的右子樹添加成p 的父節(jié)點(diǎn)的右子樹即可。
- (3)若被刪除節(jié)點(diǎn) p的左、右子樹均非空,直至讓其中序后繼結(jié)點(diǎn)頂上去。
代碼:
插入結(jié)點(diǎn):遞歸方式
查找結(jié)點(diǎn)
public boolean SearchTreeNode(TreeNode root, int data){if(root==null){return false;}else if(root.data==data){return true;}else if(root.data>data){return SearchTreeNode(root.left,data);}else{return SearchTreeNode(root.right,data);}}刪除結(jié)點(diǎn)
public boolean DeleteNode(TreeNode root, int data){//current為查找得到的節(jié)點(diǎn)TreeNode current=root;//parent為時(shí)刻更新父節(jié)點(diǎn)TreeNode parent=root;//tempParent為同時(shí)存在左右子樹的迭代臨時(shí)父節(jié)點(diǎn)TreeNode tempParent=root;//isLeft記錄current節(jié)點(diǎn)的左右屬性boolean isLeft=true;while(current.data!=data){parent=current;//到左子樹查找if(current.data>data){isLeft=true;current=current.left;}else if(current.data<data){ //到右子樹查找isLeft=false;current=current.right;}//查不到,返回falseif(current==null) {return false;}}//第一種情況:刪除節(jié)點(diǎn)為葉節(jié)點(diǎn)if(current.left==null && current.right==null){if(current==root) {root=null;}if(isLeft) {parent.left = null;}else{parent.right = null;}return true;}else if(current.right==null){ //第二種情況:刪除節(jié)點(diǎn)只有左節(jié)點(diǎn)if(current==root) {root=current.left;} else if(isLeft) {parent.left=current.left;} else {parent.right=current.left;}return true;}else if(current.left==null){ //第三種情況:刪除節(jié)點(diǎn)只有右節(jié)點(diǎn)if(current==root) {root=current.right;} else if(isLeft) {parent.left=current.right;} else {parent.right=current.right;}return true;}else{ //第四種情況:刪除節(jié)點(diǎn)均存在左節(jié)點(diǎn)和右節(jié)點(diǎn)if(current==root){root=root.left;}TreeNode tempNode=current.left;//沒(méi)有左節(jié)點(diǎn)if(tempNode.right==null){if(isLeft) {parent.left=tempNode;} else {parent.right=tempNode;}}else{ //存在左節(jié)點(diǎn),迭代到最右側(cè)子節(jié)點(diǎn),即直接前驅(qū)while(tempNode.right!=null){tempParent=tempNode;tempNode=tempNode.right;}if(isLeft){ //為左節(jié)點(diǎn),連接parent.left=tempNode;parent.left.left=current.left;}else{ //為右節(jié)點(diǎn),連接parent.right=tempNode;parent.right.left=current.left;}//刪除前驅(qū)節(jié)點(diǎn),連接if(tempNode.left==null) {tempParent.right=null;} else {tempParent.right=tempNode.left;}}return true;}}本文參考1
本文參考2
總結(jié)
以上是生活随笔為你收集整理的排序二叉树BST(binary search/sort tree)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 这或才是产品人「年终奖」的真实情况!
- 下一篇: 家电消费趋势白皮书