資料結構知識整理 二叉排序樹

2021-09-02 19:26:06 字數 4158 閱讀 1536

資料結構

查詢演算法

插入演算法

建立演算法

刪除演算法

(可回顧「基本概念」)

若在查詢的同時對錶做插入、刪除等修改操作,則被查詢的表稱為動態查詢表,反之則稱為靜態查詢表

換句話說,動態查詢表的表結構本身是在查詢過程中動態生成的,即在建立表時,對於給定值,若表中存在其關鍵字等於給定值的記錄,則返回「已存在此關鍵字」等資訊;否則插入關鍵字等於給定值的記錄。

線性表查詢演算法明顯更適合靜態查詢表。

若要對動態查詢表進行高效率的查詢,可採用二叉樹作為查詢表的組織形式,這類查詢表統稱為樹表

二叉排序樹又稱二叉查詢樹,它是一種對排序查詢都很有用的特殊二叉樹。

特徵:

1)若左子樹不為空,則左子樹上所有結點的值一定小於根結點的值。在資料結構中,對應左子樹上所有結點的關鍵字的值一定小於根結點的關鍵字的值,data.key > lchild->data.key

2)若右子樹不為空,則右子樹上所有結點的值一定大於根結點的值。

3)左子樹和右子樹都為二叉排序樹。(遞迴)

4)中序遍歷二叉排序樹可以得到乙個結點值遞增的有序線性表。

*判定樹是特殊的二叉排序樹。

typedef struct          /*定義資料元素結構體*/

element;

typedef struct /*以二叉樹結構定義查詢表*/

bstnode, *bstree; /*bstnode表示二叉樹上的結點,bstree表示指向二叉樹的指標*/

查詢演算法是建立插入刪除操作的基礎,也比較簡單。

《思路》

1)若二叉樹為空,查詢失敗,返回空指標。

2)若二叉樹不為空,比較根結點的關鍵字的值data.key和給定值key

1. 若data.key=key,則查詢成功,返回根結點的位址;

2. 若data.key<key,則遞迴查詢右子樹;

3. 若data.key>key,則遞迴查詢左子樹。

/*------------非遞迴寫法-------------*/

bstree bin_search(bstree t, keytype key)

if(!t) return null;

}/*-------------遞迴寫法--------------*/

bstree bin_search(bstree t,keytype key)

if(!t) return null;

}

需要注意的是,含有n個結點的二叉排序樹的平均查詢長度與樹的形態有關,即與二叉樹的建立演算法有關。

同一組結點,以不同的次序輸入會得到不同的二叉排序樹,其中最好的情況是二叉樹的形態與折半查詢的判定樹相似,深度達到最小。(回顧「折半查詢」)

二叉排序樹的查詢與折半查詢類似。

但就維護查詢表而言,二叉排序樹更加有效,因為無需移動資料,只需要修改指標就可以完成對查詢表的插入和刪除。因此動態查詢表更適合採用二叉樹結構。

《思路》

1)若二叉樹為空,插入新結點newnode(這裡函式引數為keytype nkey,othertype nother);

2)若二叉樹不為空,比較關鍵字的值,若新結點的關鍵字ndata.key等於根結點的關鍵字data.key,由於關鍵字唯一的原則,列印error等資訊;否則:

1. ndata.key < data.key,則遞迴插入左子樹;

2. ndata.key > data.key,則遞迴插入右子樹。

void bin_insert(bstree &t, keytype nkey, othertype nother)

if(!t) t = newnode; /*如果根結點為空,直接插入*/

if(nkey == t.data.key) cout<<"error"; /*當關鍵字重複,列印「error」*/

建立演算法的思路就如前提中說到的那樣。

乙個無序序列可以通過構造一棵二叉排序樹而變成乙個有序序列,構造過程相當於排序過程。

#define nomore 2333              /*定義nomore來控制結點數或表示輸入結束的標識*/

void bin_create(bstree &t)

}

通過關鍵字查詢待刪除結點。若不存在待刪除結點,返回「error」等資訊;若存在,刪除結點並修改相連指標。

刪除某個結點後,將有可能導致其他結點的相對位置發生變化,因此我們需給予相應處理。

刪除結點有3種情況:

1)被刪除結點既有左子樹,又有右子樹;

2)被刪除結點無左子樹;

3)被刪除節點無右子樹。

只含單子樹的情況比較簡單,將結點刪除後用下乙個結點填補就可以了。

而含有雙子樹的情況則需要找到左子樹中關鍵字最大的結點(即小於被刪除結點的關鍵字中最大的值),然後用這個結點填補被刪除結點的位置。

為什麼?

因為左子樹上所有的關鍵字必須小於根結點的關鍵字,為了在刪除結點後仍保持這一特性,必須用大於左子樹上其餘結點關鍵字的結點來填補被刪除結點的位置。

雖然右子樹上所有結點的關鍵字都大於被刪除結點,但是我們並不能直接用右子樹中的根結點(即被刪除節點的右孩子)來填補它的位置,因為右孩子本身還可能含有左子樹,這將給操作帶來十分多不必要的麻煩。

而左子樹中關鍵字最大的結點一定不含有右子樹(否則它就不是最大的),所以不會給操作帶來麻煩。

void bin_delete(bstree &t, keytype key)

p->data = s->data; /*用上面找到的結點的資訊覆蓋待刪除結點的資訊*/

if(q != p) q->rchild = s->lchild;

else q->lchild = s->lchild; /*這種情況下待刪除結點沒有左孩子*/

delete s; /*s的任務完成,撤銷儲存空間*/

}/*-------------不含右子樹------------*/

else if(!p->rchild)

p = p->lchild;

/*-------------不含左子樹------------*/

else if(!p->lchild)

p = p->rchild;

/*--------以上步驟僅完成了*p子樹的連線,還需將其與父結點*f連線-------*/

if(!f) t = p; /*當沒有父結點,即待刪除結點為根結點時*/

else if(q == f->lchild) f->lchild = p; /*原本為左子樹則掛回去左子樹位置*/

else f->rchild = p; /*反之掛回右子樹位置*/

delete q; /*q的任務完成,撤銷儲存空間*/

}

資料結構 二叉排序樹

二叉排序樹是一種特殊結構的二叉樹,它作為一種表的組織手段,通常被稱為 樹表。可以作為一種排序和檢索的手段。定義 二叉排序樹或是空樹,或是具有下述性質的二叉樹 其左子樹上所有結點的資料值均小於根結點的資料值 右子樹上所有結點的資料值均大於或等於根結點的資料值。左子樹和右子樹又各是一棵二叉排序樹。對二叉...

資料結構 二叉排序樹

二叉排序樹 binarysorttree 具有下列性質的二叉樹 1 若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值 2 若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值 3 左 右子樹也分別為二叉排序樹 include includeusing namespace std type...

資料結構 二叉排序樹

如果需要乙個滿足 支援排序性 高效插入 刪除操作 高效查詢的資料結構,怎麼做?先看看一些簡單的資料結構 1 排序順序表 陣列 查詢可以採用折半查詢演算法,時間效率為o log2n 插入 刪除操作的時間複雜度為o n 資料量大時,效率太低。2 排序單鏈表 只能採用順序查詢,時間複雜度為o n 不能採用...