在上一節中,我們為樹結點新增size域表示每顆子樹的大小,即包含的結點個數,擴張了
二叉查詢樹為其增加順序統計量的查詢功能。更為自然的想法是直接新增順序統計量rank域
到每個樹結點上。這一節我們就來看下在這樣的設計下,如何擴張來完成上一節相同的功能。
當我們插入乙個結點到二叉樹中,假設它的順序統計量為5,那麼之前二叉樹中順序統計量
大於5的結點都要更新。也就是說插入乙個新結點到對應的位置後,要不斷地查詢其後繼,
完成rank域的更新。所以可以結合習題14.2-1,再新增兩個指標域prev和next指向前趨和後繼,
使查詢前趨和後繼在o(1)內完成。
下面來看具體**。
// 新增三個新域
typedef struct _bstnode bstnode;
// 對於prev和next指標的維護,插入結點分兩種情況:
// 1.新插入結點newnode是其父結點p的左子結點,說明p->prev < newnode < p
// 2.新插入結點newnode是其父結點p的右子結點,說明p < newnode < p->next
//// 對於rank域,如果newnode沒有前趨,那麼rank置為1,否則置為newnode前趨的rank值加1
// 之後開始迭代更新,將newnode的所有後繼的rank值都加1。
void bst_insert(bstnode **root, bstnode *newnode)
// link newnode to pnode
newnode->parent = pnode;
// link pnode to newnode
// 新邏輯:維護prev, next
if (pnode == null) else if (newnode->key < pnode->key)
else
// 新邏輯:維護rank域
if (newnode->prev == null)
newnode->rank = 1;
else
newnode->rank = newnode->prev->rank + 1;
bstnode *succesor = newnode;
while ((succesor = succesor->next) != null)
}// select和rank操作變得格外簡單
bstnode *bst_os_select(bstnode *node, int i)
return null;
}int bst_os_rank(bstnode *node)
通過這一節和上一節的對比,可以看出在步驟(2)中對基礎資料結構新增不同的域,會對
步驟(3)和(4)改寫和新增新的操作產生很大影響。因此,在擴張資料結構時可以採用
試錯法,嘗試新增不同的域,權衡各種方案的優劣。
資料結構的擴張 演算法導論第14章(194)
偽 解釋 為明白os select是如何操作的,在上圖所示的順序統計圖上查詢第17小元素的查詢過程。以x為根開始,其關鍵字為26。i 17.因為在26的左子樹大小為12,故他的秩為13,因此,秩為17的節點是26的右子樹第17 13 4小得瑟元素。遞迴呼叫後,x為關鍵字41的節點,i 4,因為41的...
演算法導論筆記 14資料結構的擴張
一 概述 一些工程應用只會使用教科書式的標準資料結構,但是也會有些應用需要對現有的資料結構進行少許的創新和改造,只有很少的情況會創造全新的資料結構。二 動態順序統計 順序統計 n個元素中第i個順序統計量,就是具有第i小關鍵字的元素。對於乙個無序的集合,可以在 o n 的時間內得到任意的順序統計量。利...
《演算法導論》讀書筆記之第14章 資料結構的擴張
前言 通常我們會遇到一些問題,採用一些標準的資料結構,如雙鏈表 雜湊表或二叉查詢數時,不能夠滿足操作要求,需要對這些資料結構進行擴張,新增一些額外的資訊使得能夠完成新的操作。附加的資訊需要對資料結構的某些操作進行調整,這個是非常關鍵的步驟,決定著資料結構擴張是否能夠實現。本章主要討論了紅黑樹結構的擴...