演算法導論筆記 14資料結構的擴張

2022-07-03 16:39:09 字數 4325 閱讀 8111

一:概述

一些工程應用只會使用教科書式的標準資料結構,但是也會有些應用需要對現有的資料結構進行少許的創新和改造,只有很少的情況會創造全新的資料結構。

二:動態順序統計

順序統計:n個元素中第i個順序統計量,就是具有第i小關鍵字的元素。對於乙個無序的集合,可以在

o(n)

的時間內得到任意的順序統計量。

利用紅黑樹,可以在

o(lg n)

的時間內確定任意順序統計量,同時也能在

o(lg n)

時間內確定元素的秩,紅黑樹中,元素的秩代表中序遍歷時輸出的位置。

支援快速順序統計操作的資料結構,是在紅黑樹的基礎上進行了少許的改造,形成了順序統計樹。順序統計樹就是紅黑樹,只不過樹種每個節點,除了具有紅黑樹的key, color, left, right, p等五個性之外,還附加了另外的性質:

size

,它表示以

x為根的子樹(包括

x本身)的內(不計哨兵)節點數。並且定義哨兵的

size為0

,所以有下面的性質:

x.size = x.left.size + x.right.size + 1

下圖就是一顆順序統計樹,每個節點中,上邊是key,下邊是size:

1:確定給定秩的元素

利用size資訊,可以在o(lg n)時間內確定給定秩的元素:os-select。它返回以x為根的子樹中,指向第i小的關鍵字元素的指標,**如下:

os-select(x, i)       

r= x.left.size+1

if  i == r

return  x

else  if i < r

return  os-select(x.left, i)

else

return  os-select(x.right, i-r)

該演算法中,r表示以x為根的子樹中,節點x的秩。如果i小於r,則需要在左子樹中找第i小的元素,如果i大於r,則需要在右子樹中找第i-r小的元素。

os-select的總時間與樹的高度成正比,所以該演算法的時間複雜度為o(lg n)。

2:確定乙個元素的秩

給定元素x的指標,可以用os-rank返回元素x在樹中的秩,**如下:

os-rank(x)

r = x.left.size+1

y = x

while  y != t.root

if  y = y.p.right

r= r+y.p.left.size+1

y= y.p

returnr

在該演算法中,r表示以y為根的子樹中,x的秩。如果y為父節點的左孩子,則x在y為根的子樹中的秩也是在y.p為根的子樹中的秩。如果

y為父節點的右孩子,則x在

y.p為根的子樹中的秩,還需要加上

y.p為根的子樹中,左分支的節點數和

y.p本身所佔的位置,才是x在

y.p為根的子樹中秩。所以,最後y==root時,r就是在整個樹中的秩。

該演算法的時間複雜度為o(lgn)。

3:對子樹規模的維護

利用size屬性,可以很快的計算出順序統計量,但是,如果在統計數的改變過程中,不能在合理的時間內維護size屬性,那麼新增size屬性將是無意義的,比如,在插入或者刪除的過程中,如果維護元素

size

屬性的時間超過了

o(lg n)

,則size

變得無意義。下面就說明,插入和刪除操作,會在o(lg n)時間內完成size的維護。

插入操作,包括兩個階段,第一階段從根節點開始沿樹下降,將新節點插入到葉節點中。第二階段是沿樹上公升,做一些變色或者旋轉操作維護紅黑樹的性質。在第一階段中,為了維護size的屬性,可以將從根節點到新插入的葉子節點的路徑上的每個節點的size加1即可。這個操作的時間複雜度為o(lg n)。在第二階段,只有旋轉操作才會導致size的屬性變化,而紅黑樹的插入操作的旋轉次數最多為2次。旋轉操作是一種區域性操作,只會使得2個節點的size屬性失效,比如左旋**中,增加下面兩行就能維護size屬性:

y.size = x.size

x.size = x.left.size + x.right.size +1

左旋操作如下圖:

右旋操作也類似,所以對於插入操作來說,增加size屬性後,插入的時間複雜度還是o(lg n)。

刪除操作也是分兩個階段,第一階段找到y,要麼將y刪除,要麼將y上移,所以遍歷一條從節點y所在位置到根節點的路徑,將每個節點的size減1即可。第二階段是為了維護紅黑樹性質的變色和旋轉操作,因刪除操作最多需要3次旋轉,因而,同插入操作一樣,刪除操作的時間複雜度也是o(lg n)。

三:如何擴張資料結構

對基本的資料結構進行擴張,以支援一些附加功能,在演算法設計中是很常見的,下面是擴張一種資料結構的基本步驟:

a:選擇一種基本資料結構;

b:確定資料結構中需要維護的附加資訊;

c:檢驗基礎資料結構上的基本修改操作是否能維護附加資訊;

d:設計新的操作。

比如在利用紅黑樹進行順序統計的工作中,a:選擇了紅黑樹作為基本資料結構。b:在紅黑樹節點中新增了size屬性。c:保證插入和刪除操作仍能在o(lg n)時間內維護size屬性。d:設計順序統計的操作。

當紅黑樹作為基本資料結構時,可以證明,某些型別的附加資訊總是可以用插入和刪除操作進行有效的維護:如果

f是紅黑樹元素的附加屬性,假設對於任意節點x,

f的值僅僅依賴於

x, x.left, x.right

的資訊,還可能包括

x.left.f

和x.right.f

。那麼在插入和刪除操作中,可以在

o(lg n)

時間內維護

f的屬性。這是因為

f屬性的變動,只會影響到

x的祖先,所以修改

x.f,只需要更新

x.p.f, x.p.p.f……

。如此沿樹向上即可。

四:區間樹

區間[a,b]便於表示占用一連續時間的事件,例如查詢由時間區間構成的資料庫,找出給定時間內發生了什麼事。

可以用物件i表示區間[a,b], i.low = a;i.high = b。對於兩個區間i和j來說,如果:i.low <= j.high並且j.low <= i.high,則表示兩個區間i和j重疊。

區間樹是一種紅黑樹,樹中的元素表示乙個區間,該樹支援的操作有:插入,刪除,查詢,其中,查詢操作是返回乙個指向x的指標,x與給定的區間i重疊。如果x不存在,則返回t.nil。

下圖為一些列的區間:

為了支援查詢重疊區間的操作,:

a:選擇紅黑樹作為基本資料結構,每個節點表示乙個區間int,節點的關鍵字為區間的低點,也就是x.int.low。所以該資料結構中,中序遍歷就能按照low的次序列出各區間。

b:附加資訊為max,max表示了以x為根的子樹中,所有區間的端點high的最大值。

c:x的max值:x.max =max(x.int.high, x.left.max, x.right.max), 所以符合上面的定理,因而插入和刪除操作能在o(lgn)時間內完成。

d:插入和刪除操作與紅黑樹的一樣,這裡只需要設計search操作。它可以找出樹中,與給定區間i重疊的節點x,如果x不存在,返回t.nil。**如下:

interval-search(t, i)

x = t.root

while x != t.nil and i does not overlap x.int

if  x.left != t.nil and x.left.max >= i.low

x= x.left

else  x = x.right

return  x

該演算法能保證,如果樹中存在與i重疊的區間,該區間一定能被找到。該演算法在迴圈中,判斷x.left != t.nil and x.left.max >= i.low,如果不滿足x.left.max >= i.low,則說明左子樹中的節點的high值,都小於i的low值,所以左子樹中不存在與i重疊的區間,因而在右子樹中。

如果滿足了x.left.max >= i.low屬性,則有可能左右子樹中都會包含與i重疊的區間。首先在左子樹中找,如果左子樹中沒有的話,右子樹中一定也不存在,因為樹的關鍵字為low值,左子樹的low值肯定比右子樹小。

資料結構的擴張 演算法導論第14章(194)

偽 解釋 為明白os select是如何操作的,在上圖所示的順序統計圖上查詢第17小元素的查詢過程。以x為根開始,其關鍵字為26。i 17.因為在26的左子樹大小為12,故他的秩為13,因此,秩為17的節點是26的右子樹第17 13 4小得瑟元素。遞迴呼叫後,x為關鍵字41的節點,i 4,因為41的...

《演算法導論》第14章 資料結構的擴張 2

在上一節中,我們為樹結點新增size域表示每顆子樹的大小,即包含的結點個數,擴張了 二叉查詢樹為其增加順序統計量的查詢功能。更為自然的想法是直接新增順序統計量rank域 到每個樹結點上。這一節我們就來看下在這樣的設計下,如何擴張來完成上一節相同的功能。當我們插入乙個結點到二叉樹中,假設它的順序統計量...

《演算法導論》讀書筆記之第14章 資料結構的擴張

前言 通常我們會遇到一些問題,採用一些標準的資料結構,如雙鏈表 雜湊表或二叉查詢數時,不能夠滿足操作要求,需要對這些資料結構進行擴張,新增一些額外的資訊使得能夠完成新的操作。附加的資訊需要對資料結構的某些操作進行調整,這個是非常關鍵的步驟,決定著資料結構擴張是否能夠實現。本章主要討論了紅黑樹結構的擴...