4-12 二叉搜索樹的操作集 (30分)
本題要求實現給定二叉搜索樹的5種常用操作。
函數接口定義:
BinTree Insert( BinTree BST, ElementType X );
BinTree Delete( BinTree BST, ElementType X );
Position Find( BinTree BST, ElementType X );
Position FindMin( BinTree BST );
Position FindMax( BinTree BST );
其中BinTree結構定義如下:
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
- 函數
Insert將X插入二叉搜索樹BST並返回結果樹的根結點指針; - 函數
Delete將X從二叉搜索樹BST中刪除,並返回結果樹的根結點指針;如果X不在樹中,則打印一行Not Found並返回原樹的根結點指針; - 函數
Find在二叉搜索樹BST中找到X,返回該結點的指針;如果找不到則返回空指針; - 函數
FindMin返回二叉搜索樹BST中最小元結點的指針; - 函數
FindMax返回二叉搜索樹BST中最大元結點的指針;

輸入樣例:
10
5 8 6 2 4 1 0 10 9 7
5
6 3 10 0 5
5
5 7 0 10 3
輸出樣例:
Preorder: 5 2 1 0 4 8 6 7 10 9
6 is found
3 is not found
10 is found
10 is the largest key
0 is found
0 is the smallest key
5 is found
Not Found
Inorder: 1 2 4 6 8 9
二叉查找樹重要性質:
(1)若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
(2)若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
(3)左、右子樹也分別為二叉排序樹;
現有,如下一棵二叉查找樹。

(圖1)
現在,若要刪除圖1中,任意節點,需要考慮如下三種情況:
(1)需要刪除的節點下並沒有其他子節點。
(2)需要刪除的節點下有一個子節點(左或右)。
(3)需要刪除的節點下有兩個子節點(既左右節點都存在)。
第一種情況直接刪除即可,下面,直接討論第二種情況。
若我們要刪除的是3號節點,由圖1可以看到,它下面還有一個4號子節點。由下圖2,可以看出,對於這種辦法,我們只需要想辦法,讓5號節點的左子樹的指針指向4就可以了。

(圖2)
第三種情況,既我們要刪除的節點下,有2個子節點。如圖3,我們先在需要刪除的節點的右子樹中,找到一個最小的值(因為右子樹中的節點的值一定大於根節點)。然后,用找到的最小的值與需要刪除的節點的值替換。然后,再將最小值的原節點進行刪除(圖4)。

(圖3)

1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 typedef int ElementType; 5 typedef struct TNode *Position; 6 typedef Position BinTree; 7 struct TNode{ 8 ElementType Data; 9 BinTree Left; 10 BinTree Right; 11 }; 12 13 void PreorderTraversal( BinTree BT ); /* 先序遍歷,由裁判實現,細節不表 */ 14 void InorderTraversal( BinTree BT ); /* 中序遍歷,由裁判實現,細節不表 */ 15 BinTree Insert( BinTree BST, ElementType X ); 16 BinTree Delete( BinTree BST, ElementType X ); 17 Position Find( BinTree BST, ElementType X ); 18 Position FindMin( BinTree BST ); 19 Position FindMax( BinTree BST ); 20 int main() 21 { 22 BinTree BST, MinP, MaxP, Tmp; 23 ElementType X; 24 int N, i; 25 BST = NULL; 26 scanf("%d", &N); 27 for ( i=0; i<N; i++ ) { 28 scanf("%d", &X); 29 BST = Insert(BST, X); 30 } 31 printf("Preorder:"); PreorderTraversal(BST); printf("\n"); 32 MinP = FindMin(BST); 33 MaxP = FindMax(BST); 34 scanf("%d", &N); 35 for( i=0; i<N; i++ ) { 36 scanf("%d", &X); 37 Tmp = Find(BST, X); 38 if (Tmp == NULL) printf("%d is not found\n", X); 39 else { 40 printf("%d is found\n", Tmp->Data); 41 if (Tmp==MinP) printf("%d is the smallest key\n", Tmp->Data); 42 if (Tmp==MaxP) printf("%d is the largest key\n", Tmp->Data); 43 } 44 } 45 scanf("%d", &N); 46 for( i=0; i<N; i++ ) { 47 scanf("%d", &X); 48 BST = Delete(BST, X); 49 } 50 printf("Inorder:"); 51 InorderTraversal(BST); 52 printf("\n"); 53 return 0; 54 } 55 /* 你的代碼將被嵌在這里 */ 56 void PreorderTraversal( BinTree BT ) 57 { 58 if(BT==NULL) return; 59 else{ 60 printf(" %c",BT->Data); 61 PreorderTraversal(BT->Left); 62 PreorderTraversal(BT->Right); 63 } 64 } 65 void InorderTraversal( BinTree BT ) 66 { 67 if(BT==NULL) return; 68 else{ 69 InorderTraversal(BT->Left); 70 printf(" %c",BT->Data); 71 InorderTraversal(BT->Right); 72 } 73 } 74 BinTree Insert( BinTree BST, ElementType X ) 75 { 76 if(!BST)//如果BST為空的話,返回只有一個節點的樹 77 { 78 BST=(BinTree)malloc(sizeof(struct TNode)); 79 BST->Data=X; 80 BST->Left=NULL; 81 BST->Right=NULL; 82 } 83 else//如果BST不是為空的話 84 {//開始尋找要插入的位置 85 if(X<BST->Data) 86 BST->Left=Insert(BST->Left,X); 87 else if(X>BST ->Data) 88 BST->Right=Insert(BST->Right,X); 89 } 90 return BST; 91 } 92 BinTree Delete( BinTree BST, ElementType X ) 93 { 94 BinTree Tmp; 95 if(!BST) printf("Not Found\n"); 96 else{ 97 if(X<BST->Data) 98 BST->Left=Delete(BST->Left,X); 99 else if(X>BST->Data) 100 { 101 BST->Right=Delete(BST->Right,X); 102 } 103 else//考慮如果找到這個位置,並且有左節點或者右節點或者沒有節點三種情況 104 { 105 if(BST->Left && BST->Right) { 106 Tmp=FindMin(BST->Right); /* 在右子樹中找到最小結點填充刪除結點 */ 107 BST->Data = Tmp ->Data; 108 BST->Right=Delete(BST->Right,BST->Data);/* 遞歸刪除要刪除結點的右子樹中最小元素 */ 109 } 110 else 111 { /* 被刪除結點有一個或沒有子結點*/ 112 Tmp = BST; 113 if(!BST->Left) BST = BST->Right; /*有右孩子或者沒孩子*/ 114 else if(!BST->Right) BST = BST->Left;/*有左孩子,一定要加else,不然BST可能是NULL,會段錯誤*/ 115 free(Tmp); /*如無左右孩子直接刪除*/ 116 } 117 } 118 } 119 return BST; 120 } 121 Position Find( BinTree BST, ElementType X ) 122 { 123 if(!BST) return NULL; 124 if(BST->Data==X) return BST; 125 else if(X<BST->Data) { 126 return Find(BST->Left,X); 127 } 128 else if(X>BST->Data) 129 { 130 return Find(BST->Right,X); 131 } 132 return BST; 133 } 134 Position FindMin( BinTree BST ) 135 { 136 if(BST!=NULL) 137 { 138 while(BST->Left) 139 BST=BST->Left; 140 } 141 return BST; 142 } 143 Position FindMax( BinTree BST ) 144 { 145 if(BST!=NULL) 146 { 147 while(BST->Right) 148 BST=BST->Right; 149 } 150 return BST; 151 }
