16.二叉排序樹,16二叉排序

來源:互聯網
上載者:User

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

/*二叉樹的二叉鏈表結點結構定義*/typedef struct BiTNode                        //結點結構{    int data;                                            //結點資料    Struct BiTNode *lchild,*rchild;       //左右孩子指標}BiTNode,*BiTree;   
二、二叉排序樹操作演算法 1.二叉排序樹的查詢操作
/*遞迴尋找二叉排序樹T中是否存在key,   * 指標f指向T的雙親,其初始調用值為NULL    *若尋找成功,則指標p指向該資料元素結點,並返回TRUE;否則指標p指向尋找路徑上訪問的最後一個結點並返回FALSE*/Status SearchBST(BiTree T,int key,BiTree f,BiTree *p){    if(!T)                            //尋找不成功(為空白樹)    {            *p=f;            return FALSE;    }    else if(key==T->data)  //尋找成功    {            *p=T;            return TRUE;    }    else if(key<T->data)            return SearchBST(T->lchild,key,T,p);        //在左子樹繼續尋找    else            return SearchBST(T->rchild,key,T,p);        //在右子樹繼續尋找  }
執行個體:    假如有一資料集合={62,88,58,47,35,73,51,99,37,93},尋找的關鍵字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(key<T->data)語句。即當要尋找關鍵字小於當前結點時執行語句,由於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(key<T->data)語句,再次遞迴調用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){    BiTree p,s;    /*調用尋找函數尋找是否存在該關鍵字*/    //a.若尋找不成功    if(!SearchBST(*T,key,NULL,&p))        {          s=(BiTree)malloc(sizeof(BiTNode));    //為結點s開闢一段記憶體空間          s->data=key;                                       //將關鍵字存放到s指向結點的資料域中          s->lchid=s->rchild=NULL;                //初始化結點s的左右指標域         if(!p)                *T=s;                //插入s為新的根結點         else if(key<p->data)//若關鍵字小於p結點資料值,插入s為結點p的左孩子                p->lchild = s;             else                        //若關鍵字大於p結點資料值,插入s為結點p的右孩子                p->rchild=s;       }    /*樹中已有關鍵字相同的結點,不再插入*/    else    {            return FALSE;        }}
舉例:假如我們調用函數是"InsertBST(T,93);",那麼結果就是FALSE;假如調用函數為"InsertBST(T,95);",那麼一定是就是在93的結點增加一個右孩子95,並返回TRUE。需要注意的是,由於插入演算法事先調用了SearchBST(*T,key,NULL,&p)尋找演算法且使用中序遍曆二叉樹,最終我們可知指標p指向的結點為93. 3.構建二叉排序樹演算法
 
/*假如有一個資料集={62,88,58,47,35,73,51,99,37,93}    * 構建一個二叉排序樹*/int i;int a[0]={62,88,58,47,35,73,51,99,37,93};BiTree T=NULL;for(i=0;i<10;i++){    InsertBST(&T,a[i]);}
4.二叉排序樹刪除操作演算法
(1)採用遞迴方式對二叉排序樹T尋找key,找到後調用Delete函數刪除該結點/*若二叉排序樹T中存在關鍵字等於key的資料元素時,則刪除該資料元素結點    *    並返回TRUE;否則返回FALSE*/
Status DeleteBST(BiTree *T,int key){     if(!*T)    //不存在關鍵字等於key的資料元素            return FALSE;    else    {        if(key==(*T)->data)    //找到關鍵字等於key的資料元素                return Delete(T);    //調用Delete函數刪除該結點        else if(key<(*T)->data)                return DeleteBST(&(*T)->lchild,key);            else                return DeleteBST(&(*T)->rchild,key);    }   }
(2)Delete刪除演算法
/*從二叉排序樹中刪除結點p,並重接它的左或右子樹*/Status Delete(BiTree *p){     BiTree q,s;    /*情況二:刪除結點p的右子樹或左子樹為空白*/    if((*p)->lchild==NULL)               //a.右子樹空則只需重接它的左子樹    {            q=*p;    *p=(*p)->lchild;    free(q);    }        else if((*p)->rchild==NULL)        //b.只需重接它的右子樹    {            q=*p;    *p=(*p)->rchild;    free(q);    //將指標p指向的結點    }    //情況三:左右子樹均不為空白    else    {            q=*p;    s=(*p)->lchild;            while(s->rchild)            //轉左,然後向右到盡頭(找待刪結點的前驅)            {                 q=s;    s=s->rchild;                       }            (*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次,即跟結點就是要找的結點,最多也不會超過樹的深度,即二叉排序樹的尋找效能取決於二叉排序樹的形狀。   

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.