演算法導論-二叉排序樹

來源:互聯網
上載者:User

一、定義與性質

定義 
  二叉排序樹(Binary Sort Tree)又稱二叉尋找(搜尋)樹(Binary Search Tree)。其定義為:二叉排序樹或者是空樹.

性質
  (1) 二叉排序樹中任一結點x,其左(右)子樹中任一結點y(若存在)的關鍵字必小(大)於x的關鍵字。
  (2) 二叉排序樹中,各結點關鍵字是惟一的。
  注意:實際應用中,不能保證被尋找的資料集中各元素的關鍵字互不相同,所以可將二叉排序樹定義中BST性質(1)裡的"小於"改為"大於等於",或將BST性質(2)裡的"大於"改為"小於等於",甚至可同時修改這兩個性質。
  (3) 按中序遍曆該樹所得到的中序序列是一個遞增有序序列。


二、插入與刪除

       插入與刪除操作是二叉排序樹中最常用也是最重要的兩個操作。

       插入過程是:
  (a)若二叉排序樹T為空白,則為待插入的關鍵字key申請一個新結點,並令其為根;
  (b)若二叉排序樹T不為空白,則將key和根的關鍵字比較:
           (i)若二者相等,則說明樹中已有此關鍵字key,無須插入。
           (ii)若key<T→key,則將key插入根的左子樹中。
           (iii)若key>T→key,則將它插入根的右子樹中。
  子樹中的插入過程與上述的樹中插入過程相同。如此進行下去,直到將key作為一個新的葉結點的關鍵字插入到二叉排序樹中,或者直到發現樹中已有此關鍵字為止。

     刪除過程:

     

(1) 進行尋找
       尋找時,令p指向當前訪問到的結點,parent指向其雙親(其初值為NULL)。若樹中找不到被刪結點則返回,否則被刪結點是*p。
(2) 刪去*p。
       刪*p時,應將*p的子樹(若有)仍串連在樹上且保持BST性質不變。按*p的孩子數目分三種情況進行處理。

         刪除*p結點的三種情況
         a.*p是葉子(即它的孩子數為0)
       無須串連*p的子樹,只需將*p的雙親*parent中指向*p的指標域置空即可。

   

         b.*p只有一個孩子*child
       只需將*child和*p的雙親直接連接後,即可刪去*p。
            注意:*p既可能是*parent的左孩子也可能是其右孩子,而*child可能是*p的左孩子或右孩子,故共有4種狀態。


            c.*p有兩個孩子
       先令q=p,將被刪結點的地址儲存在q中;然後找*q的中序後繼*p,並在尋找過程中仍用parent記住*p的雙親位置。*q的中序後繼*p一定是*q的右子樹中最左下的結點,它無左子樹。因此,可以將刪去*q的操作轉換為刪去的*p的操作,即在釋放結點*p之前將其資料複製到*q中,就相當於刪去了*q。

三、代碼清單

#include<stdio.h>#include<stdlib.h>#define maxSize 20  #define maxWidth 20  typedef int KeyType; //假定關鍵字類型為整數typedef struct node { //結點類型KeyType key; //關鍵字項struct node *lchild,*rchild;//左右孩子指標} BSTNode,BSTree;//typedef BSTNode *BSTree; //BSTree是二叉排序樹的類型//先序遍曆  void preOrder(BSTree *BT)  {  if(BT!= NULL)  {  printf("%d",BT->key);  preOrder(BT->lchild);  preOrder(BT->rchild);  }  }  //中序遍曆  void inOrder(BSTree *BT)  {  if(BT!= NULL)  {  inOrder(BT->lchild);  printf("%d",BT->key);  inOrder(BT->rchild);  }  }  //後序遍曆  void postOrder(BSTree *BT)  {  if(BT!= NULL)  {  postOrder(BT->lchild);  postOrder(BT->rchild);  printf("%d",BT->key);  }  } //層次法列印樹  void dispTree(BSTree *BT)  {  BSTree *stack[maxSize],*p;  int level[maxSize][2],top,n,i,width=4;  if(BT!=NULL)  {  printf("Display a tree by hollow means.\n");  top=1;  stack[top]=BT;//push root point to stack.  level[top][0]=width;  while(top>0)  {  p=stack[top];  n=level[top][0];  for(i=1;i<=n;i++)  printf(" ");  printf("%d",p->key);  for(i=n+1;i<maxWidth;i+=2)  printf("--");  printf("\n");  top--;  if(p->rchild!=NULL)  {  top++;  stack[top]=p->rchild;  level[top][0]=n+width;  level[top][1]=2;  }  if(p->lchild!=NULL)  {  top++;  stack[top]=p->lchild;  level[top][0]=n+width;  level[top][1]=1;  }  }  }  }  /* 向二叉排序樹中加入一個結點 要改變指標,需要傳遞指標的指標*/int InsertNode(BSTree **tree, KeyType key){BSTNode *p= NULL, *parent = NULL;BSTNode *pNewNode = (BSTNode *)malloc(sizeof(BSTNode));if (pNewNode==NULL){return -1;}/* 建立結點賦值,特別是左右子結點指標要賦值為NULL */pNewNode->key = key;pNewNode->lchild = NULL;pNewNode->rchild = NULL;/* 二叉排序樹是空樹 */if (*tree==NULL){*tree = pNewNode;return 0;}else{p = *tree;/* 尋找插入位置 */while (NULL != p){/* key值已在二叉排序樹中 */if (p->key == key){return 0;}else{parent = p;p = (p->key < key) ? p->rchild : p->lchild;}}if (parent->key < key){parent->rchild = pNewNode;}else{parent->lchild = pNewNode;}return 0;}}//刪除節點 /* 通過值尋找並刪除一個結點 */ int delNode(BSTree **tree, KeyType key) {     BSTNode *p = NULL, *q = NULL, *parent = NULL, *child = NULL;     p = *tree;     /* parent為NULL表示根結點的父親為NULL */     while (NULL != p)     {         if (p->key == key)         {             break;         }         else         { parent = p;         p = (p->key < key) ? p->rchild : p->lchild;         }     }     /* p為NULL時, 表示沒有找到結點值為key的結點 */     if (NULL == p)     {         return 0;     }     /* p, q現在都是儲存了待刪結點指標 */     q = p;          /* 待刪結點有兩個兒子結點,進行一下轉化 */     if (NULL != p->lchild && NULL != p->rchild)     {//找中序後繼,先右拐,然後左走到底         parent = p;         p = p->rchild;         while (NULL != p->lchild)         {             parent = p;             p = p->lchild;         }         /* p中儲存了待刪結點右子樹中最左下的結點指標, parent中就儲存了該結點父親指標 */         child = p->rchild;     }          /* parent儲存待刪結點的父親結點指標, child儲存了待刪結點的兒子結點     //實際刪除的是待刪節點的直接後繼,下面是刪除直接後繼的過程,(待刪結點至多隻有一個兒子, 有兩個會轉化為0個或1個右結點)     */     // 待刪結點是根結點,且只有一個兒子     if (NULL == parent)     {if(p->lchild!=NULL) *tree = p->lchild;else *tree = p->rchild;     }     else     {         /*待刪結點是父親結點的左兒子*/         if (parent->lchild == p)         {             parent->lchild = child;         }         else         {             parent->rchild = child;         }//將實際刪除的節點的key值賦給原先要刪除的節點         if (p != q)         {             q->key = p->key;         }     }     free(p);     return 0; }//二叉排序樹尋找BSTNode* SearchBST(BSTree *T,KeyType key){ //在二叉排序樹T上尋找關鍵字為key的結點,成功時返回該結點位置,否則返回NUllif(T==NULL) //遞迴的終結條件return NULL; //T為空白,尋找失敗;if(key==T->key)//成功,返回找到的結點位置{printf("Got it!");return T;}if(key<T->key)return SearchBST(T->lchild,key);elsereturn SearchBST(T->rchild,key);//繼續在右子樹中尋找} //SearchBSTint main(){int n;BSTree *B=NULL;printf("Input number to initialize a BSTree:");while(1){scanf("%d",&n);if(n==0) break;InsertNode(&B, n);}dispTree(B); printf("PreOrder:");preOrder(B);printf("\n");printf("Search a node:");scanf("%d",&n);SearchBST(B,n);printf("\n");printf("Delete a node:");scanf("%d",&n);delNode(&B,n);dispTree(B); printf("PreOrder:");preOrder(B);printf("\n");return 1;}

運行結果:


  參考:http://www.cnblogs.com/ljphhj/archive/2012/02/25/2367821.html

    http://blog.csdn.net/zhongjiekangping/article/details/4564293

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.