資料結構 二叉查詢樹

2022-08-31 18:27:08 字數 4059 閱讀 1048

使二叉樹成為二叉查詢樹的性質是,對於樹中的每個節點x,它的左子樹中所有關鍵字值小於x的關鍵字值,而它的右子樹中所有關鍵字值大於x的關鍵字值。這意味著,該樹所有的元素以某種統一的方式排序。

二叉查詢樹是一棵特殊的二叉樹,二叉查詢樹中節點的結構與二叉樹種節點的結構相同,關鍵在於可以在二叉查詢樹上可以執行的操作以及對其進行操作的演算法。二叉查詢樹的宣告如下:

#ifndef  _tree_h

struct treenode;

typedef struct treenode *position;

typedef struct treenode *searchtree;

searchtree makeempty(searchtree t);

position find(elementtype x,searchtree t);

position findmin(searchtree t);

position findmax(searchtree t);

searchtree insert(elementtype x,searchtree t);

searchtree delete(elementtype x,searchtree t);

elementtype retrieve(position p);

#endif

二叉查詢樹節點的結構:

struct treenode

elementtype element;

searchtree left;

searchtree right;

makeempty主要用於建立一棵空樹。例程如下:

searchtree makeempty(searchtree t)

if(t!=null)                            //遞迴終止條件

makeempty(t->left); makeempty(t->right);

free(t);//實際執行的操作,釋放空間

return null;

遞迴演算法必須有遞迴終止條件,此處的終止條件就是樹(子樹)的根節點為null。

查詢操作是在樹中查詢儲存要檢索的關鍵字元素的節點的指標,返回值為指向節點的指標型別,如果沒有找到則返回null。二叉查詢樹的重要特性就是元素排列是有順序的,因此查詢元素時可以根據這一特性進行有「方向」的查詢(向某乙個分支進行查詢),而不是檢索所有的元素,這樣查詢操作的時間複雜度最大為二叉查詢樹的深度,二叉查詢樹的平均深度為o(logn),因此二叉查詢樹的查詢操作的時間複雜度為o(logn),相對於線性資料結構的o(n)有很大的進步。

利用二叉查詢樹的遞迴性質,利用遞迴演算法進行查詢操作是非常簡單的。核心思想就是利用要查詢的元素與(子樹)根節點處的元素的對比(大於小於等於)來選擇查詢的方向(左右子樹)或者找到要查詢的元素。同時處理根節點為空的情況。**如下:

position find(elementtype x,searchtree t)

if(t==null)

return null;

if(xelement)

return find(x,t->left);

else if(x>t->element)

return find(x,t->right);

else

return t;

findmin與findmax操作比較簡單,查詢最小值只需要找到最左邊的節點,最大值只需要找到最右邊的節點。演算法只需要在左(右)子樹為空時返回上一層節點即可,同時也需要注意最開始為null的情況。在樹結構上的操作最直觀的思路是使用遞迴,但是也可以使用迭代的思想。這裡findmin使用遞迴,findmax使用迭代,**如下:

position findmin(searchtree t)

if(t==null)

return null;

else

if(t->left==null)

return t;

else

return findmin(t->left);

positon findmax(searchtree t)

if(t!=null)

while(t->right!=null)

t=t->right;

return t;

插入操作例程也比較簡單,類似與查詢操作,關鍵在於找到要插入的元素應該所處的位置,找到位置後就需要建立節點,並且將新建立的節點與原來的樹「連線」起來(將新建立節點的指標放到其父節點的左或者右子節點指標位置)。利用遞迴思想處理插入操作,關鍵在於找到遞迴終止條件,這裡的遞迴終止條件是要插入的樹為空樹(根節點為null的情況)。具體**如下:

searchtree insert(elementtype x,searchtree t)

if(t==null)      //遞迴終止條件

t=malloc(sizeof(struct treenode));

if(t==null)

error;

else

t->element=x;

t->left=t->right=null;

else

if(xelement)

t->left=insert(x,t->left);

if(x>t->element)

t->right=insert(x,t->right);

//當要插入的元素已存在的情況,此時的操作需要看樹本身定義

return t;    

當要插入的元素已存在時,可以在節點中乙個新的域中儲存元素的頻率。或者key值只是更大的資料結構的一部分,此時可以使用鍊錶或者另一棵樹來儲存具有相同key值得資料。具體要根據需求決定。

刪除操作是所有的操作中最複雜的操作,原因在於刪除樹中的節點不僅僅是釋放一塊記憶體空間那麼簡單。在從樹中刪除乙個節點後,還需要保持二叉查詢樹的特性(根節點的左子樹中的元素要比根節點中的元素小,右子樹中的元素要比根節點中的元素大)。比較簡單的情況是要刪除的節點只有乙個子節點或者沒有子節點的情況。當沒有子節點時,直接刪除節點(釋放節點占用的空間)即可。同時需要將其父節點的某乙個子節點指標置為null。(在遞迴處理樹操作時,只需要考慮當前節點作為根的子樹即可,其父節點的處理是在遞迴函式返回後處理的,即只要在處理當前節點時考慮好怎麼處理對其子節點呼叫本函式後的返回值即可,則遞迴機制執行時會處理好當前根節點的父節點的處理,這是遞迴思想的處理思路。)當只有乙個子節點時,刪除當前節點,將子節點直接作為要刪除的節點的父節點的子節點。複雜的是當有兩個子節點時,這時左子樹需要保持不變,而把要刪除的節點刪除掉,同時將右子樹中最小的節點拿來替換掉刪除掉的節點,即將右子樹中最小的節點的左子樹設定為已刪除節點的左子樹,同時將已刪除節點的父節點的某乙個子節點指標設定為自己。同時,還需要從右子樹中刪除自己(原來最小的節點)。此時因為最小節點最多隻會有右子樹,則可以使用刪除節點時最有乙個子節點的情況進行處理。實際上,由於在利用遞迴思想進行操作時,當前處理節點的父節點很難獲取,因此實際中並沒有刪除有兩個子節點的要刪除節點,只是將資料換為其右子樹中最小節點的資料,這樣比較簡單。具體**如下:

searchtree delete(element x,searchtree t)

position tempcell;

if(t==null)

error(「element not found」);

else

if(xelement)

t->left=delete(x,t->left);

else

if(x>t->element)

t->right=delete(x,t->right);

else       //找到了要刪除的元素

if(t->left&&t->right)    //左右子樹都不為空

tempcell=findmin(t->right);

t->element=tempcell->element;

t->right=dlete(t->element,t->right);

else       //只有左子樹或者右子樹,或者沒有子節點

tempcell=t;

if(t->left==null)

t=t->right;

if(t->right=null)

t=t->left;

free(tempcell);

return t;

(資料結構)二叉查詢樹

樹,是一種資料結構。它是由n個有限節點組成乙個具有層次關係的集合。特點 樹的基本術語 節點的度 節點擁有的子樹的數目。葉子 度為零的節點。分支節點 度不為零的節點。樹的度 樹中節點的最大的度。層次 根節點的層次為1,其餘節點的層次等於該節點的雙親的層次加1。樹的高度 樹中節點的最大層次。無序樹 如果...

資料結構 樹 二叉查詢樹

wiki 首先是名稱 二叉查詢樹英文叫binary search tree,這個在很多演算法題目中很常見所以要記住,特別是英文題目中。也叫做二叉排序樹,二叉搜尋樹等等。具體的定義比較官方,用自己的話說,首先它肯定是二叉樹,其次,當前節點的左子葉元素值比當前節點小,右子葉元素值比當前節點大,所以節點均...

資料結構之二叉查詢樹

針對二叉查詢樹的操作 增刪改查 的時間和樹的高度成正比,比如都有10個節點的乙個樹,樹高為4和樹高為10的操作時間肯定是不同的,這個時間實際上是o lgn 二叉查詢樹的期望的樹高是lgn,從而基本動態集合的操作平均時間為 lgn 通常二叉查詢樹基於鍊錶實現,每個節點儲存左,右子節點,如果想更方便的實...