深入学习二叉树(四) 二叉排序树
深入學(xué)習(xí)二叉樹(四) 二叉排序樹
1 前言
數(shù)據(jù)結(jié)構(gòu)中,線性表分為無序線性表和有序線性表。
無序線性表的數(shù)據(jù)是雜亂無序的,所以在插入和刪除時(shí),沒有什么必須遵守的規(guī)則,可以插入在數(shù)據(jù)尾部或者刪除在數(shù)據(jù)尾部。但是在查找的時(shí)候,需要遍歷整個(gè)數(shù)據(jù)表,導(dǎo)致無序線性表的查找效率低。
有序線性表的數(shù)據(jù)則相反,查找數(shù)據(jù)時(shí)的時(shí)候因?yàn)閿?shù)據(jù)是有序的,可以用二分法、插值法、斐波那契查找法來實(shí)現(xiàn)。但是,當(dāng)進(jìn)行插入和刪除操作時(shí),需要維護(hù)表中數(shù)據(jù)的有序性,會(huì)耗費(fèi)大量的時(shí)間。
那么,我們希望找到一種數(shù)據(jù)結(jié)構(gòu),既可以有較高的插入和刪除效率,并且具備較高的查找效率,因此,二叉排序樹應(yīng)運(yùn)而生。
2 二叉排序樹
2.1 定義
二叉排序樹(Binary Sort Tree),又稱二叉查找樹(Binary Search Tree),也稱二叉搜索樹。二叉排序樹或者是一棵空樹,或者是具有下列性質(zhì)的二叉樹:
(1)若左子樹不空,則左子樹上所有結(jié)點(diǎn)的值均小于或等于它的根結(jié)點(diǎn)的值;
(2)若右子樹不空,則右子樹上所有結(jié)點(diǎn)的值均大于或等于它的根結(jié)點(diǎn)的值;
(3)左、右子樹也分別為二叉排序樹;
2.2 構(gòu)造一棵二叉排序樹
現(xiàn)有序列:61 87 59 47 35 73 51 98 37 93
構(gòu)造過程如下:
1)索引 i = 0,A[i] = 61,結(jié)點(diǎn)61作為根結(jié)點(diǎn),如圖2.1:
2)索引 i = 1,A[1] = 87, 87 > 61,且結(jié)點(diǎn)61右孩子為空,故81為61結(jié)點(diǎn)的右孩子,如圖2.2:
3)索引 i = 2,A[i] = 59,59 <61,且結(jié)點(diǎn)61左孩子為空,故59為61結(jié)點(diǎn)的左孩子,如圖2.3:
4)索引 i = 3,A[3] = 47,47 < 59,且結(jié)點(diǎn)59左孩子為空,故47為59結(jié)點(diǎn)的左孩子,如圖2.4:
5)索引 i = 4,A[4] = 35,35 < 47,且結(jié)點(diǎn)47左孩子為空,故35為47結(jié)點(diǎn)的左孩子,如圖2.5:
采用同樣規(guī)則遍歷整個(gè)數(shù)組得到如圖2.6所示的一棵排序二叉樹。
2.3 二叉排序樹查找
由二叉樹的遞歸定義性質(zhì),二叉排序樹的查找同樣可以使用如下遞歸算法查找。
如果樹是空的,則查找結(jié)束,無匹配。
如果被查找的值和根結(jié)點(diǎn)的值相等,查找成功。否則就在子樹中繼續(xù)查找。如果被查找的值小于根結(jié)點(diǎn)的值就選擇左子樹,大于根結(jié)點(diǎn)的值就選擇右子樹。
在理想情況下,每次比較過后,樹會(huì)被砍掉一半,近乎折半查找。
遍歷打印可以使用中序遍歷,打印出來的結(jié)果是從小到大的有序數(shù)組。
查找代碼:
對(duì)于圖2.6所示的二叉排序樹,若查找結(jié)點(diǎn)key為47則可以查找成功,若查找結(jié)點(diǎn)key為75,樹中不存在key為75的結(jié)點(diǎn),故查找失敗,則查找指針p指向查找路徑的最后一個(gè)結(jié)點(diǎn),即結(jié)點(diǎn)73。
2.4 二叉排序樹插入
二叉排序的插入是建立在二叉排序的查找之上的,插入一個(gè)結(jié)點(diǎn),就是通過查找發(fā)現(xiàn)該結(jié)點(diǎn)合適插入位置,把結(jié)點(diǎn)直接放進(jìn)去。 其實(shí)在2.2節(jié)中一步步構(gòu)造二叉排序樹的過程中就是結(jié)點(diǎn)插入過程。由此可以得出二叉排序樹插入規(guī)則如下:
若查找的key已經(jīng)有在樹中,則p指向該數(shù)據(jù)結(jié)點(diǎn)。
若查找的key沒有在樹中,則p指向查找路徑上最后一個(gè)結(jié)點(diǎn)。
例如:若在圖2.6展示的二叉排序樹中插入結(jié)點(diǎn)數(shù)據(jù)為60的結(jié)點(diǎn)。
首先查找結(jié)點(diǎn)數(shù)據(jù)為60的結(jié)點(diǎn),二叉排序樹中不存在結(jié)點(diǎn)為60的結(jié)點(diǎn),因此查找失敗。此時(shí)查找指針p指向查找路徑最后一個(gè)結(jié)點(diǎn)即指向59結(jié)點(diǎn)。由于60>59且59結(jié)點(diǎn)右子樹為空,故將60結(jié)點(diǎn)作為59結(jié)點(diǎn)的右孩子,插入完成。插入后的二叉排序樹如圖2.8所示。
插入代碼:
2.5 二叉排序樹刪除
二叉樹的刪除可不再像二叉樹的插入那么容易了,以為刪除某個(gè)結(jié)點(diǎn)以后,會(huì)影響到樹的其它部分的結(jié)構(gòu)。
刪除的時(shí)候需要考慮以下幾種情況:
1)刪除結(jié)點(diǎn)為葉子結(jié)點(diǎn);
2)刪除的結(jié)點(diǎn)只有左子樹;
3)刪除的結(jié)點(diǎn)只有右子樹
4)刪除的結(jié)點(diǎn)既有左子樹又有右子樹。
考慮前三種情況,處理方式比較簡(jiǎn)單。
例如:若要?jiǎng)h除圖2.8中的結(jié)點(diǎn)93,則直接刪除該結(jié)點(diǎn)即可。刪除后二叉排序樹如圖2.9所示:
若要?jiǎng)h除的結(jié)點(diǎn)為結(jié)點(diǎn)35,結(jié)點(diǎn)35只有右子樹,只需刪除結(jié)點(diǎn)35,將右子樹37結(jié)點(diǎn)替代結(jié)點(diǎn)35即可。刪除后的二叉排序樹如圖2.10所示:
刪除只有左子樹的結(jié)點(diǎn)與此情況類似。
情況4相對(duì)比較復(fù)雜,對(duì)于待刪除結(jié)點(diǎn)既有左子樹又有右子樹的情形,最佳辦法是在剩余的序列中找到最為接近的結(jié)點(diǎn)來代替刪除結(jié)點(diǎn)。這種代替并不會(huì)影響到樹的整體結(jié)構(gòu)。那么最為接近的結(jié)點(diǎn)如何獲取呢?
可以采用中序遍歷的方式來得到刪除結(jié)點(diǎn)的前驅(qū)和后繼結(jié)點(diǎn)。選取前驅(qū)結(jié)點(diǎn)或者后繼結(jié)點(diǎn)代替刪除結(jié)點(diǎn)即可。
例如:待刪除的結(jié)點(diǎn)為47,圖2.8中二叉排序樹的中序遍歷序列為35 37 47 51 59 60 61 73 87 93 98。則結(jié)點(diǎn)47的前驅(qū)結(jié)點(diǎn)為37,則直接將37結(jié)點(diǎn)替代47結(jié)點(diǎn)即可。替換后的二叉排序樹如圖2.11所示:
刪除代碼:
3 結(jié)語
二叉排序樹是一種查找與插入效率均較為高效的數(shù)據(jù)結(jié)構(gòu),同時(shí),二叉排序樹也是二叉樹學(xué)習(xí)中的重點(diǎn)與難點(diǎn)。希望通過本篇的學(xué)習(xí)能夠掌握二叉排序樹的查找、插入與刪除等基本操作,也希望讀者給出指導(dǎo)意見。
總結(jié)
以上是生活随笔為你收集整理的深入学习二叉树(四) 二叉排序树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dtm文件生成等高线 lisp_DEM、
- 下一篇: 信息源按加工深度划分_铝合金插铣加工切削