二叉排序樹的建立、先序/中序/后序遍歷、查找


一、定義與性質

 

定義 
  二叉排序樹(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。

 

三、代碼清單

 

[cpp]  view plain  copy
 
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #define maxSize 20    
  4. #define maxWidth 20    
  5.   
  6. typedef int KeyType; //假定關鍵字類型為整數  
  7. typedef struct node { //結點類型  
  8.     KeyType key; //關鍵字項  
  9.     struct node *lchild,*rchild;//左右孩子指針  
  10. } BSTNode,BSTree;  
  11. //typedef BSTNode *BSTree; //BSTree是二叉排序樹的類型  
  12.   
  13. //先序遍歷    
  14. void preOrder(BSTree *BT)    
  15. {    
  16.     if(BT!= NULL)    
  17.     {    
  18.         printf("%d-",BT->key);    
  19.         preOrder(BT->lchild);    
  20.         preOrder(BT->rchild);    
  21.   
  22.     }    
  23. }    
  24.   
  25. //中序遍歷    
  26. void inOrder(BSTree *BT)    
  27. {    
  28.     if(BT!= NULL)    
  29.     {    
  30.         inOrder(BT->lchild);    
  31.         printf("%d-",BT->key);    
  32.         inOrder(BT->rchild);    
  33.     }    
  34. }    
  35.   
  36. //后序遍歷    
  37. void postOrder(BSTree *BT)    
  38. {    
  39.     if(BT!= NULL)    
  40.     {    
  41.         postOrder(BT->lchild);    
  42.         postOrder(BT->rchild);    
  43.         printf("%d-",BT->key);    
  44.     }    
  45. }   
  46.   
  47. //層次法打印二叉排序樹  
  48. /* 以先序遍歷的方式打印二叉排序樹 */    
  49. void dispTree(BSTree *BT)    
  50. {    
  51.     BSTree *stack[maxSize],*p;    
  52.     int level[maxSize][2],top,n,i,width=4;    
  53.     if(BT!=NULL)    
  54.     {    
  55.         printf("Display a tree by hollow means.\n");    
  56.         top=1;    
  57.         stack[top]=BT;//push root point to stack.    
  58.         level[top][0]=width;    
  59.           
  60.     while(top>0)    
  61.         {    
  62.             p=stack[top];    
  63.             n=level[top][0];    
  64.             for(i=1;i<=n;i++)    
  65.                 printf(" ");    
  66.             printf("%d",p->key);    
  67.             for(i=n+1;i<maxWidth;i+=2)    
  68.                 printf("--");    
  69.             printf("\n");    
  70.             top--;    
  71.               
  72.       if(p->rchild!=NULL) //右子樹先入棧,后出棧   
  73.             {    
  74.                 top++;    
  75.                 stack[top]=p->rchild;    
  76.                 level[top][0]=n+width;    
  77.                 level[top][1]=2;    
  78.             }    
  79.               
  80.       if(p->lchild!=NULL)  //左子樹后入棧,先出棧  
  81.             {    
  82.                 top++;    
  83.                 stack[top]=p->lchild;    
  84.                 level[top][0]=n+width;    
  85.                 level[top][1]=1;    
  86.             }  //if  
  87.         }  //while  
  88.     }  //if  
  89. //dispTree()   
  90.   
  91. /* 向二叉排序樹中加入一個結點  
  92. 要改變指針,需要傳遞指針的指針*/  
  93. /* return 0表示插入成功, return -1表示插入失敗 */   
  94. int InsertNode(BSTree **tree, KeyType key)  
  95. {  
  96.     BSTNode *p= NULL, *parent = NULL;  
  97.     BSTNode *pNewNode = (BSTNode *)malloc(sizeof(BSTNode));  
  98.     if (pNewNode==NULL)  
  99.     {  
  100.         return -1;  
  101.     }  
  102.       
  103.   /* 新建結點賦值,特別是左右子結點指針要賦值為NULL,葉子節點 */  
  104.   /* 二叉排序樹新插入的結點都是葉子節點 */   
  105.     pNewNode->key = key;  
  106.     pNewNode->lchild = NULL;  
  107.     pNewNode->rchild = NULL;  
  108.       
  109.   /* 二叉排序樹是空樹 */  
  110.     if (*tree==NULL)  
  111.     {  
  112.         *tree = pNewNode;  
  113.         return 0;  
  114.     }  
  115.     else  
  116.     {  
  117.   
  118.         p = *tree;  
  119.         /* 尋找插入位置 */  
  120.         while (NULL != p) /* 待插入的結點以葉子節點方式插入 */  
  121.         {  
  122.             /* key值已在二叉排序樹中 */  
  123.             if (p->key == key)  
  124.             {  
  125.                 return 0;  
  126.             }  
  127.             else  
  128.             {  
  129.                 parent = p;  
  130.                 p = (p->key < key) ? p->rchild : p->lchild; //key是待插入結點   
  131.             }  
  132.         } //while,結束時NULL == p,此時已經到了葉子節點位置   
  133.         if (parent->key < key)  
  134.         {  
  135.             parent->rchild = pNewNode;  
  136.         }  
  137.         else  
  138.         {  
  139.             parent->lchild = pNewNode;  
  140.         } //else   
  141.         return 0;  
  142.     } //else  
  143. //InsertNode   
  144.   
  145. //刪除節點  
  146.  /* 通過值查找並刪除一個結點 */  
  147.  int delNode(BSTree **tree, KeyType key)  
  148.  {  
  149.      BSTNode *p = NULL, *q = NULL, *parent = NULL, *child = NULL;  
  150.      p = *tree;  
  151.      /* parent為NULL表示根結點的父親為NULL */  
  152.      while (NULL != p)  
  153.      {  
  154.          if (p->key == key) //此時找到待刪除的結點p   
  155.          {  
  156.              break;  
  157.          }  
  158.          else  
  159.          { parent = p;  
  160.            p = (p->key < key) ? p->rchild : p->lchild;  
  161.          }  
  162.      } //while   
  163.      /* p為NULL時, 表示沒有找到結點值為key的結點 */  
  164.      if (NULL == p) /* 到達葉子節點仍未查找到要刪除的結點 */   
  165.      {  
  166.          return -1;  
  167.      }  
  168.      /* p, q現在都是保存了待刪結點指針 */  
  169.      q = p; //此時p->key == key   
  170.        
  171.      /* 待刪結點有兩個兒子結點,進行一下轉化 */  
  172.      if (NULL != p->lchild && NULL != p->rchild)  
  173.      {  
  174.     //找中序后繼,先右拐,然后左走到底  
  175.          parent = p;  
  176.          p = p->rchild; /* 進入右子樹 */  
  177.          while (NULL != p->lchild)  
  178.          {  
  179.              parent = p;  
  180.              p = p->lchild;  
  181.          }  
  182.          /* p中保存了待刪結點右子樹中最左下的結點指針, parent中就保存了該結點父親指針 */  
  183.          child = p->rchild;  
  184.      }  
  185.      else if(NULL == p -> lchild)  
  186.           child = p -> rchild;  
  187.      else  
  188.          child = p -> lchild;   
  189.        
  190.      /* parent保存待刪結點的父親結點指針, child保存了待刪結點的兒子結點 
  191.       
  192. //實際刪除的是待刪節點的直接后繼,下面是刪除直接后繼的過程,(待刪結點至多只有一個兒子, 有兩個會轉化為0個或1個右結點) 
  193.      */  
  194.      // 待刪結點是根結點,且只有一個兒子  
  195.      if (NULL == parent)  
  196.      {  
  197.           if(p->lchild!=NULL) *tree = p->lchild;  
  198.           else *tree = p->rchild;  
  199.      }  
  200.      else  
  201.      {  
  202.          /*待刪結點是父親結點的左兒子*/  
  203.          if (parent->lchild == p)  
  204.          {  
  205.              parent->lchild = child;  
  206.          }  
  207.          else  
  208.          {  
  209.              parent->rchild = child;  
  210.          }  
  211.     //將實際刪除的節點的key值賦給原先要刪除的節點  
  212.          if (p != q)  
  213.          {  
  214.              q->key = p->key;  
  215.          }  
  216.      }  
  217.      free(p);  
  218.      return 0;  
  219.  } //delNode  
  220.   
  221. //二叉排序樹查找  
  222. BSTNode* SearchBST(BSTree *T,KeyType key)  
  223. //在二叉排序樹T上查找關鍵字為key的結點,成功時返回該結點位置,否則返回NUll  
  224.     if(T==NULL) //遞歸的終結條件  
  225.         return NULL; //T為空,查找失敗;  
  226.     if(key==T->key)  
  227.         //成功,返回找到的結點位置  
  228.     {  
  229.         printf("Got it!");  
  230.         return T;  
  231.     }  
  232.   
  233.     if(key<T->key)  
  234.         return SearchBST(T->lchild,key);  
  235.     else  
  236.         return SearchBST(T->rchild,key);//繼續在右子樹中查找  
  237. //SearchBST  
  238.   
  239. int main()  
  240. {  
  241.     int n;    
  242.     BSTree *B=NULL;  
  243.     printf("Input number to initialize a BSTree:");  
  244.     while(1)  
  245.     {  
  246.         scanf("%d",&n);  
  247.         if(n==0) break; //遇到0時停止輸入,0並不入樹   
  248.         InsertNode(&B, n);  
  249.     }     
  250.     dispTree(B);   
  251.     printf("PreOrder:");  
  252.     preOrder(B);  
  253.     printf("\n");  
  254.     printf("Search a node:");  
  255.     scanf("%d",&n);  
  256.     SearchBST(B,n);  
  257.     printf("\n");  
  258.     printf("Delete a node:");  
  259.     scanf("%d",&n);  
  260.     delNode(&B,n);  
  261.     dispTree(B);   
  262.     printf("PreOrder:");  
  263.     preOrder(B);  
  264.     printf("\n");  
  265.     system("pause");  
  266.     return 1;  
  267. }  



四、程序運行結果

 


 

出處:http://blog.csdn.NET/silangquan/article/details/8065243


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM