資料結構 排序二叉樹(BST) 插入刪除查詢 中序遍歷 銷燬(後序遍歷)

gaopengtttt發表於2016-10-29
結構概念如下:

二叉排序樹(binary sort tree):

1、也叫做二叉查詢樹

2、如果他的左子樹不為空,則左子樹上所有結點的

值均小於他的根結構的值

3、如果他的右子樹不為空,則右子樹上所有結點的

值均大於他的根結構的值

4、他的左右子樹分別為二叉排序樹

5、按照二叉樹中序遍歷其返回結果樹有序的

下面就是一顆典型的二叉樹,只是是字母,可以將字母換位字母的順序進行審視,但是它不是平衡二叉樹


排序二叉樹(BST)的優點在於進行資料查詢比較方便,因為他是按照資料來到的順序進行如上的規則進行的
建樹,只要如上的規則進行查詢就能找到需要的資料。但是其缺點也是顯而易見,樹的深度是不可控制的
而且可能極不均勻,考慮 1 2 3 4 5 6 7,這樣的資料建樹全部節點都在左子樹上,級不均勻。那麼給
搜尋資料的效能帶來的較大的影響,所以引入了AVL樹平衡二叉樹,這個在後面再說

關於排序二叉樹BST的各種操作都使用了遞迴演算法,給出遞迴演算法一張我認為很好的圖:


這張圖實際體現了遞迴的真諦 順序呼叫反向返回,這個列子和圖來自小甲魚C影片也可能來自大話資料結構
上面的程式碼實際上是:

void print()
{
    char a;
    scanf("%c",&a);
      if(a!='#') print();
      if(a!='#') printf("%c",a);
}

關於遞迴的經典 費布那切數列和漢諾塔等都可以瞭解一下;
下面迴歸正題,直接給出程式碼和測試用例。說明程式碼大部分來自大話資料結構,銷燬和中序遍歷是我自己寫的,但是我自己進行了理解。
主要刪除資料比較難,分為3種情況
1、刪除節點的左子樹為空,更改*p = (*p)->rchild;注意這裡的*p代表的是parent->child,所以這樣做就是將父節原來指向刪除節點的指標,指向刪除節點的下一個右孩子
2、刪除節點的右子樹為空,同理更改*p = (*p)->lchild;注意這裡的*p代表的是parent->child,所以這樣做就是將父節原來指向刪除節點的指標,指向刪除節點的下一個左孩子
3、刪除節點左右子樹都不為空,需要進行找到直接前驅或者直接後繼節點進行資料代替。這個就比較複雜直接看程式碼吧
分別進行討論。 
其他操作相對簡單不用再秒素就是遞迴,但是需要注意排序返回資料是用中序遍歷,銷燬樹用的是後序遍歷。
程式碼如下:

點選(此處)摺疊或開啟

  1. 標頭檔案
  2. bstort.h
  3. #include<stdio.h>
  4. typedef int bool;
  5. #define false 0
  6. #define true 1
  7. #define xfree(x) free(x); x = NULL;

  8. typedef struct BiTnode
  9. {
  10.         int data;
  11.         struct BiTnode *lchild,*rchild;
  12. } BiTnode,*BiTree;


  13. bool SearchBst(BiTree T,int key,BiTree *f,BiTree *p);
  14. bool InsertBst(BiTree *T,int key) ;
  15. void Inordervist(const BiTree T);
  16. void BTreedestroy(BiTree tree);
  17. bool DeleteBst(BiTree *T,int key);
  18. bool Delete(BiTree *p);

點選(此處)摺疊或開啟

  1. 實現程式
  2.  bstort.c
  3. #include<stdio.h>
  4. #include<stdlib.h>
  5. #include"bstort.h"
  6. /*
  7.    T = Bst root node
  8.    key = search key
  9.    f = T's parent node,used if search failed save last search node pointer
  10.    if search failed last T is NULL,inital vlaues is NULL,
  11.    is sucuess f is pointer to p's parent poniter,
  12.    p = if sucess p is pointer to find node pointer,if failed is pointer to last
  13.    search node pointer

  14. */

  15. bool SearchBst(BiTree T,int key,BiTree *f,BiTree *p)
  16. {
  17.         if(!T)
  18.         {
  19.                 *p = *f;
  20.                 return false;
  21.         }
  22.         else if(key == T->data)
  23.         {
  24.                 *p = T;
  25.                 return true;
  26.         }
  27.         else if(key < T->data)
  28.         {
  29.                 *f = T;
  30.                 return SearchBst(T->lchild,key,f,p);
  31.         }
  32.         else
  33.         {
  34.                 *f = T;
  35.                 return SearchBst(T->rchild,key,f,p);
  36.         }
  37. }

  38. /*
  39.    T = Bst root node
  40.    key = key to insert
  41.    */
  42. bool InsertBst(BiTree *T,int key)
  43. {
  44.         BiTree p = NULL ,s = NULL ,f=NULL;
  45.         if(!SearchBst(*T,key,&f,&p)) //init NULL,KEY,NULL,&P=NULL
  46.         {
  47.                 s = (BiTree)calloc(1,sizeof(BiTnode));
  48.                 s->data =key;
  49.                 s->lchild = s->rchild = NULL;

  50.                 if(!p)
  51.                 {
  52.                         printf("Create Tree with key:%d\n",key);
  53.                         *T = s; //create Bst one node
  54.                 }
  55.                 else if(key < p->data)
  56.                 {
  57.                         printf("Insert Key To Tree(left):%d\n",key);
  58.                         p->lchild = s;
  59.                 }
  60.                 else
  61.                 {
  62.                         printf("Insert Key To Tree(right):%d\n",key);
  63.                         p->rchild = s;
  64.                 }
  65.                 return true;
  66.         }
  67.         else
  68.         {
  69.                 return false;
  70.         }
  71. }
  72. /*
  73. inorder traversal method
  74. */

  75. void Inordervist(const BiTree T)
  76. {
  77.         if(T)
  78.         {
  79.                 Inordervist(T->lchild);
  80.                 printf("%d\n",T->data);
  81.                 Inordervist(T->rchild);
  82.         }
  83. }

  84. /*
  85. postorder traversal method to destroy tree
  86. */

  87. void BTreedestroy(BiTree T)
  88. {

  89.         if(T)
  90.         {
  91.         BTreedestroy(T->lchild);
  92.         BTreedestroy(T->rchild);
  93.         printf("Delete node for Key%d\n",T->data);
  94.         xfree(T);
  95.         }
  96. }


  97. bool DeleteBst(BiTree *T,int key)//use **p *p is parent->child,here is very import
  98. {
  99.         if(!*T)//
  100.         {
  101.                 printf("no delete data %d find\n........\n",key);
  102.                 return true;
  103.         }
  104.         else
  105.         {
  106.                 if(key == (*T)->data)
  107.                 {
  108.                         return Delete(T);
  109.                 }
  110.                 else if(key < (*T)->data)
  111.                 {
  112.                         return DeleteBst(&(*T)->lchild,key);//here use lchild pointer's address
  113.                 }
  114.                 else
  115.                 {
  116.                         return DeleteBst(&(*T)->rchild,key);
  117.                 }
  118.         }
  119. }

  120. bool Delete(BiTree *p)//use **p *p is parent->child,here is very import
  121. {
  122.         BiTree q,s;

  123.         printf("delete data :%d\n........\n",(*p)->data);
  124.         if((*p)->rchild == NULL)//right node is NULL
  125.         {
  126.                 q = *p;
  127.                 *p = (*p)->lchild;
  128.                 xfree(q);
  129.         }
  130.         else if((*p)->lchild ==NULL)//leaf node is NULL
  131.         {
  132.                 q = *p;
  133.                 *p = (*p)->rchild;
  134.                 xfree(q);
  135.         }
  136.         else //exp:use ...20 30 50 (60 delete)... use 50 replace 60 ,use replace not free find node
  137.         {
  138.                 q = *p;
  139.                 //---------------
  140.                 s = (*p)->lchild;
  141.                 while(s->rchild) //if s->rchild is NULL q=*p mean (*p)->lchild s have no right node
  142.                 {
  143.                         q = s;
  144.                         s = s->rchild;
  145.                 }
  146.                 (*p)->data = s->data;

  147.                 /*-------------- here find near delete node small data,frist find lchild then find
  148.                 all small data root node then find last right node this is require data*/

  149.                 if(q!=*p) //if (*p)->lchild s have right node
  150.                 {
  151.                         q->rchild =s->lchild;
  152.                 }
  153.                 else // if (*p)->lchild s have no right node
  154.                 {
  155.                         q->lchild = s ->lchild;
  156.                 }
  157.                 xfree(s);//free find last right node,beacuse it's data used for find node
  158.         }
  159. }





點選(此處)摺疊或開啟

  1. 測試用例和主函式
  2. main.c
  3. #include<stdio.h>
  4. #include"bstort.h"


  5. int main(void)
  6. {
  7.         BiTree root = NULL;
  8.         InsertBst(&root,10);
  9.         InsertBst(&root,20);
  10.         InsertBst(&root,40);
  11.         InsertBst(&root,5);
  12.         InsertBst(&root,1);
  13.         InsertBst(&root,-1);
  14.         InsertBst(&root,-20);
  15.         InsertBst(&root,100);
  16.         printf("Use inorder traversal method:\n");
  17.         Inordervist(root);
  18.         DeleteBst(&root,30);
  19.         DeleteBst(&root,10);
  20.         printf("Use inorder traversal method:\n");
  21.         Inordervist(root);
  22.         printf("Use postorder traversal method destroy Bst:\n");
  23.         BTreedestroy(root);
  24. }

結構如下:
Create Tree with key:10
Insert Key To Tree(right):20
Insert Key To Tree(right):40
Insert Key To Tree(left):5
Insert Key To Tree(left):1
Insert Key To Tree(left):-1
Insert Key To Tree(left):-20
Insert Key To Tree(right):100
Use inorder traversal method:
-20
-1
1
5
10
20
40
100
no delete data 30 find
........
delete data :10
........
Use inorder traversal method:
-20
-1
1
5
20
40
100
Use postorder traversal method destroy Bst:
Delete node for Key-20
Delete node for Key-1
Delete node for Key1
Delete node for Key100
Delete node for Key40
Delete node for Key20
Delete node for Key5

這裡首先演示了建樹,然後演示了中序遍歷返回有序的結果,然後刪除一個不包含的資料30,
然後刪除一個包含的資料10,然後再次進行中序遍歷,最後使用後續遍歷刪除。
可以看到結果如我們希望的。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2127320/,如需轉載,請註明出處,否則將追究法律責任。

相關文章