前言:通常我們會遇到一些問題,採用一些標準的資料結構,如雙鏈表、雜湊表或二叉查詢數時,不能夠滿足操作要求,需要對這些資料結構進行擴張,新增一些額外的資訊使得能夠完成新的操作。附加的資訊需要對資料結構的某些操作進行調整,這個是非常關鍵的步驟,決定著資料結構擴張是否能夠實現。本章主要討論了紅黑樹結構的擴張,介紹了兩種擴張方式。第一種方式擴張使得紅黑色能夠支援動態集合上順序統計,快速找出集合中第i小的數,或給出某個元素在集合的全序中的排名。第二種方式擴張使得紅黑色能夠進行區間操作,可以很快地找到集合中覆蓋的區間。關於紅黑色請參考第13章,
1、動態順序統計
在第九章介紹了順序統計的概念,大概的意思是在包含有n個元素的集合中,第i個順序統計量指的是該集合中第i小的元素。在乙個無序的集合中,任意順序統計量都可以在o(n)時間內找到,詳細情況可以參考書中在此基礎上修改紅黑樹的結構,使得任意的順序統計量都可以再o(lgn)時間內確定。向紅黑樹的結構中新增乙個size域,表示包含自身節點的當前節點的子樹節點的數目。這樣修改後可以快速支援順序統計量操作,將這種修改後的紅黑樹叫做:順序統計量樹t。修改後的結構如下所示:
struct例如給定紅黑樹的乙個節點x,則size[x] = size[left[x]]+size[right[x]]+1。size[x]為包含以x為根的子樹的節點數(包含x本身),即子樹的大小。如果哨兵定義為0,即設定size[nil[t]]=0。rbtreenode
;
下面給出乙個修改後的紅黑樹的例子,如下圖所示:
紅黑樹是二叉排序樹,按照中序遍歷從小到大輸出紅黑樹中的關鍵字。從圖中可以看出,新增size域後,很方便看出每個節點的子樹的節點數目(包含自身節點)。書中在後面討論這種結構的操作,分別討論如下:
(1)檢索具有給定排序的元素
過程os_select(x,i)返回乙個指向以x為根的子樹中包含第小關鍵字的結點的指標,即為了找出順序統計量樹t中的第i小關鍵字,可以呼叫os_select(root[t],i)。書中給出了偽**如下:
os_select(x,i)該過程類似二分查詢,每一次遞迴呼叫都在順序統計數中下降一層,故最壞情況下os_select的總時間與樹的高度成正比,紅黑樹的高度為lgn。故os_select的執行時間為:o(lgn)。r = size[left[x]]+1; //
先計算x的處於的位置
if i = r //
x正好是第i小的關鍵字
then return
x;
else
if i < r //
x比第i關鍵字大,則在其左子樹查詢
then return
os_select(left[x],i)
else
return os_select(right[x],i-r) //
x比第i關鍵字小,則在其右子樹查詢
(2)確定乙個元素的秩(位置)
給定指向一順序統計樹t中節點x的指標,求x在順序統計樹中序遍歷得到的線性序中的位置。書中給出了os_rank(t,x)過程的偽**:
os_rank(t,x)從程式總可以看出當y == root[t]時候迴圈終止,此時以y為根的子樹是課完整樹,此時r值是這顆整樹中key[x]的秩。while迴圈中的每一次迭代花o(1)時間,且y在每次迭代中沿樹上公升一層,故在最壞情況下0s_rank的執行時間與樹的高度成正比:對含n個節點的順序統計樹時間為o(lgn)。r = size[left[x]]+1; //
獲取以x為根子樹中x的位置(中序遍歷)
y =x;
while y != root[t] //
從下向上直到根節點
doif y = right[p[y]] //
如果是右子樹
then r = r + size[left[p[y]]]+1
; y = p[y]; //
向上移動
return r;
(3)對子樹規模的維護
在紅黑樹中新增size域後,能夠通過os_select和os_rank迅速計算出所需的順序統資訊。通過修改紅黑樹的插入和刪除操作,在此過程是通過旋轉來修改size域。關於這部分需要在紅黑樹的基礎上進行改進,比較複雜,暫時沒有實現。
2、如何擴張資料結構
對一種資料結構的擴張過程分為四個步驟:
1)選擇基礎資料結構
2)確定要在基礎資料結構中新增哪些資訊
3)驗證可用基礎資料結構上的基本修改操作來維護這些新新增的資訊
4)設計新的操作
書中給出了對紅黑樹進行擴張的定理,並給出了證明,這個看的時候有些難度,暫時跳過了。大概意思就是說當紅黑樹被選作基礎資料結構時,某些型別的附加資訊總是可以用插入和刪除來進行有效地維護。
3、區間樹
這小結講的是擴張紅黑樹以支援由區間構成的動態集合上的操作。區間可以很方便的表示各占用一段連續時間的一些事情。區間樹是一種動態集合進行維護的紅黑樹,該集合中的每個元素x都包含在乙個區間int[x]。區間樹支援下列操作:
interval_insert(t,x):將包含區間域int的元素x插入到區間樹t中
interval_delete(t,x):從區間樹t中刪除元素x
interval_search(t,i):返回乙個指向區間樹t中元素x的指標,使int[x]與i重疊,若集合中無此元素存在,則返回nil[t]。
修改紅黑樹得到的區間樹如下圖所示:
從圖可以看出,對區間樹以每個節點的左端點值進行中序變數即可得到有序的序列。有了區間樹的結果就很容易實現其相關操作。
結構體(第十四章 )
目錄 一 結構體簡單執行例項 二 結構體具體使用 宣告定義 初始化訪問 三 結構陣列 四 指向結構的指標 宣告初始化 訪問一 結構體最簡單的執行例項 結構體是描述結構如何組合的主要方法。以下為建立圖書目錄的乙個簡單例項 include define maxtitle 41 define maxaut...
演算法導論第十四章 資料結構的擴充套件
這章的主要內容是通過紅黑樹的兩個擴充套件例子掌握如何對一種資料結構在原有基礎上進行擴充套件。來為自己所用 擴充套件一種資料結構大致可以分為4個步驟 1.選擇一種基礎資料結構.2.確定基礎資料結構中要維護的附加資訊.3.檢驗基礎資料結構中的基本操作能否維護附加資訊 4.設計一些新操作 它是紅黑樹的乙個...
第十四章約束
約束 constraint 是一種保證資料完整性的規則。約束設定在單個字段或者多個字段組合上,寫入這些欄位的行資料必須要符合約束的規則 約束的五種型別 not null 非空約束,指定某列的所有行資料不能包含空值 unique 唯一性約束,指定列或者列的組合的所有行資料必須唯一 primary ke...