Introduction to Algorithm(chapter 14)

數據結構的擴張,針對某些應用通過在原有的數據結構上增加某些信息(需要維護該類信息保持原有數據結構的性質不變)就可以添加一些操作來簡化問題。

動態順序統計:在紅黑樹的基礎上,在每個節點i上增加一個域size,表示以該節點爲根的子樹中節點的個數(包括該節點本身)。

   求取一系列數中的第j大的數,對於根節點root,根節點的左子樹有t=size(left(root))個節點,那麼根節點就是第t+1大的節點,如果j==t+1那麼根節點即爲所求,如果j<t+1,那麼第j大的節點肯定在左子樹中,否則肯定在右子樹中,且爲右子樹中第(j-t-1)大,遞歸調用即可。僞代碼如下:

   OS-SELECT(x,i)

r = size(left(x))+1;

if x = i

return x;

else if i<r

return OS-SELECT(left(x),i);

else

return OS-SELECT(right(x),i-r);

利用快排中的選擇算法的時間爲O(n),而現在降爲O(log n),因爲紅黑樹的高度是logn,在每次遞歸調用後都在順序統計樹中下降一層,總時間與樹的高度成正比。

   確定x節點在樹中的秩(即排序後的大小位置如第j大那麼秩就爲j),分析該問題:對這顆樹進行中序遍歷後,就可以確定x節點的秩,因此只需求出中序條件下排在x節點前面的節點個數即可。從樹的高度角度來看,從x節點開始向上根節點進行歸納分析,對於節點x,它的左子樹肯定排在它的前面,當它是父母的左孩子時x下面的節點僅有左子樹在它前面,當它是父母的右孩子時,它的父母以及父母的左子樹都排在它的前面,通過x不斷上升到根節點即可得出總個排在它前面的節點個數。僞代碼如下: 

循環不變量是:r = rank of key[x] in subtree rooted at x. and y = x.

   OS-RANK(T,x)

  r = size(left(x))+1;

y=x;

//從當前節點不斷上升到根節點進行統計

while y != root

if y = right(p(y))

r = r + 1 + size(left(p(y)));//這裏加1是父親節點,size(left(p(y)))是父親的左子樹個數

y=p(y);

return r;

y在每次迭代都上升一層,故時間與樹的高度成正比,爲O(log n)

對於插入和刪除操作中對於size域的維護都需要O(log n)的時間


擴張數據結構的一般步驟:

1.選擇合適的基礎數據結構

2.確定要在基礎數據結構中添加哪些信息

3.驗證可用基礎數據結構上的基本修改操作來維護這些新添加的信息

4.設計新的操作

measurement:將對操作的不利影響降低到最小,如果隻影響局部信息的話不要影響全局信息;例如如果把每個節點的秩作爲附加信息的話,那麼OS-SELECT和OS-RANK將會更快,然而插入一個新節點時,將會影響到樹中每個節點的秩,而附加信息是子樹的規模,那麼插入節點僅影響到O(logn)節點的附加信息,這樣就將影響侷限在局部範圍內而不是全局範圍。

區間樹:在紅黑樹的基礎上每個節點維護三個信息,low(x),high(x),max(x),其中[low(x),high(x)]代表該節點的區間,其中每個節點的關鍵字是low(x),而max(x)表示包括在x節點在內的所有子樹節點中的最大的端點,即

max(x) =  max(high(x),max(left(x)),max(right(x)))

查找重疊子區間和上面查找第i大的元素類似,都是從根開始下降到合適的位置(找到或者空):



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章