16 二叉排序樹

2021-12-30 05:24:06 字數 3584 閱讀 1447

一、二叉排序樹如果要查詢的資料集是有序線性表且是順序儲存的,查詢可以用折半、插值、斐波那契等查詢演算法來實現。然後,由於有序,當我們在插入和刪除操作上,就需要耗費大量的時間。下面將要學習的二叉排序樹,就是一種既可以使得插入和刪除效率不錯,又可以比較高效率地實現查詢的演算法。為此,構造一棵二叉排序樹的目的並不是為了排序,而是為了提供查詢和插入刪除關鍵字的速度。1.二叉排序樹概念二叉排序樹(binary sort tree),又稱為二叉查詢樹,或者是一棵空樹,或者是具有下列性質的二叉樹。 ◆若它的左子樹不空,則左子樹上所有結點的值均小於它的根結構(雙親結點)的值; ◆若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點(雙親結點)的值; ◆它的左、右子樹也分別為二叉排序樹。2.二叉樹結點結構

/*二叉樹的二叉鍊錶結點結構定義*/

typedef struct bitnode //結點結構

bitnode,*bitree;

二、二叉排序樹操作演算法1.二叉排序樹的查詢操作/*遞迴查詢二叉排序樹t中是否存在key,

* 指標f指向t的雙親,其初始呼叫值為null

*若查詢成功,則指標p指向該資料元素結點,並返回true;否則指標p指向查詢路徑上訪問的最後乙個結點並返回false*/

status searchbst(bitree t,int key,bitree f,bitree *p)

else if(key==t->data) //查詢成功

else if(keydata)

return searchbst(t->lchild,key,t,p); //在左子樹繼續查詢

else

return searchbst(t->rchild,key,t,p); //在右子樹繼續查詢

}例項: 假如有一資料集合=,查詢的關鍵字key=93。 使用二叉排序樹查詢演算法步驟如下: ①根據二叉排序樹定義將該資料集合構造成一棵二叉排序樹(中序遍歷);

②呼叫二叉排序樹查詢演算法searchbst(t,93,null,p)查詢關鍵字,其中,searchbst函式是乙個可遞迴執行的函式,引數t是乙個二叉樹鍊錶、key代表要查詢的關鍵字、二叉樹f指向t的雙親。當t指向根結點時,f的初值就為null,它在遞迴時有用,最後的引數p是為了查詢成功後可以得到查詢到的結點位置。 ③ if(!t)語句。用來判斷當前二叉樹是否到葉子結點,此時當前t指向根結點62的位置,由於t不為空,故該語句片段不執行。 ④esle if(key==t->data)語句。即查詢到相匹配的關鍵字執行語句,顯然93!=62,故該語句片段不執行。 ⑤else if(keydata)語句。即當要查詢關鍵字小於當前結點時執行語句,由於93>62,故該語句片段不執行。 ⑥else語句。即當即當要查詢關鍵字大於當前結點時執行語句,93>62,所以以遞迴呼叫searchbst(t->rchild,key,t,p)。此時,t指向了62的右孩子88,f指向88的雙親結點,即62。如圖:

⑦此時第二層searchbst,因93比88大,所以執行else語句,再次遞迴呼叫searchbst(t->rchild,key,t,p)。此時t指向了88的右孩子99。

⑧此時第三層searchbst,因93比99小,所以執行else if(keydata)語句,再次遞迴呼叫searchbst(t->lchild,key,t,p)。此時t指向了99的左孩子93。

⑨第四層searchbst,因key等於t->data,所以執行第10~11行,此時指標p指向93所在的結點並返回true到第三層、第二層、第一層,最終返回函式true。2.二叉排序樹的插入操作所謂二叉排序樹的插入,即將關鍵字放到樹中的合適位置。(1)二叉排序樹的插入演算法

/*當二叉排序樹t中不存在關鍵字等於key的資料元素時,

* 插入key並返回true,否則返回false*/

status insertbst(bitree *t,int key)

/*樹中已有關鍵字相同的結點,不再插入*/

else

}舉例:假如我們呼叫函式是"insertbst(t,93);",那麼結果就是false;假如呼叫函式為"insertbst(t,95);",那麼一定是就是在93的結點增加乙個右孩子95,並返回true。需要注意的是,由於插入演算法事先呼叫了searchbst(*t,key,null,&p)查詢演算法且使用中序遍歷二叉樹,最終我們可知指標p指向的結點為93.3.構建二叉排序樹演算法

/*假如有乙個資料集=

* 構建乙個二叉排序樹*/

int i;

int a[0]=;

bitree t=null;

for(i=0;i<10;i++)

4.二叉排序樹刪除操作演算法

(1)採用遞迴方式對二叉排序樹t查詢key,找到後呼叫delete函式刪除該結點 /*若二叉排序樹t中存在關鍵字等於key的資料元素時,則刪除該資料元素結點 * 並返回true;否則返回false*/

status deletebst(bitree *t,int key)

}(2)delete刪除演算法/*從二叉排序樹中刪除結點p,並重接它的左或右子樹*/

status delete(bitree *p)

else if((*p)->rchild==null) //b.只需重接它的右子樹

//情況三:左右子樹均不為空

else

(*p)->data=s->data; //s指向被刪結點的直接前驅

if(q!=*p)

q->rchild=s->lchild; //重接q的右子樹

else

q->lchild=s->lchild; //重接q的左子樹

free(s);

}return true;

}原始碼分析: q=*p; *p=(*p)->rchild; free(q); 作用:將指標p指向的結點賦值給新結點q,並使p指標指向的左結點,即實現了重接右子樹,再釋放結點q.

三、二叉排序樹總結二叉排序樹是以鏈結的方式儲存,保持了鏈結儲存結構在執行插入或刪除操作時不用移動元素的優點,只要找到合適的插入和刪除位置後,僅需修改鏈結指標即可。插入刪除的時間效能比較好,而對於二叉排序樹的查詢,走的就是從根結點到要查詢的結點的路徑,其比較次數等於給定值的結點在二叉排序樹的層數。極端情況,最少為1次,即跟結點就是要找的結點,最多也不會超過樹的深度,即二叉排序樹的查詢效能取決於二叉排序樹的形狀。

二叉排序樹

在複習資料結構,把這個東西總結一下。這種結構是動態查詢表,這種動態是相對靜態查詢 順序查詢,折半查詢,分塊查詢等 來說的。對於各種靜態鍊錶,要達到查詢複雜度為o logn 必須要求有序 而要使插入刪除複雜度為o 1 必須是鍊錶儲存。動態查詢表就可以同時滿足這兩者。動態查詢表的特點是表結構本身在查詢過...

二叉排序樹

name 二叉排序樹相關操作 author unimen date 2011 10 8 13 14 21 刪除結點比較麻煩,總結如下 4大種情況 1 結點p無右孩子 將該點的左孩子變為其在雙親中的同位孩子 1 p為其雙親的左孩子時將其的左孩子變為雙親的左孩子 2 p為其雙親的右孩子時將其的左孩子變為...

二叉排序樹

include include include include struct tree node void insert node struct tree node int void pre order struct tree node void in order struct tree node ...