一、二叉搜索樹的特點
二叉搜索樹的特點:對於樹中的每個節點X,它的左子樹中所有關鍵字值小於X的關鍵字值,而它的右子樹中所有關鍵字值大於X的關鍵字值。
根據這個性質,對一個二叉樹進行中序遍歷,如果是單調遞增的,則可以說明這個樹是二叉搜索樹。
LeetCode題目98:驗證二叉搜索樹(https://leetcode-cn.com/problems/validate-binary-search-tree/)就可以對這個二叉樹進行中序遍歷,然后判斷是否單調遞增的,如果是單調遞增的,說明是二叉搜索樹。否則不是二叉搜索樹。
二、二叉搜索樹的查找
過程:首先和根節點進行比較,如果等於根節點,則返回。如果小於根節點,則在根節點的左子樹進行查找。如果大於根節點,則在根節點的右子樹進行查找。

1 /* 查找以t為根節點的樹中,是否包含x */ 2 Position Find(ElementType x, SearchTree t) 3 { 4 if (t == NULL) { 5 return NULL; 6 } else if (x < t->element) { 7 return Find(x, t->left); 8 } else if (x > t->element) { 9 return Find(x, t->right); 10 } else { 11 return t; 12 } 13 }
三、查找最大值和最小值
查找最小值:從根開始,如果有左兒子,則向左進行。直到左兒子為空,則當前節點為最小值。

1 Position FindMin(SearchTree t) 2 { 3 if (t == NULL) { 4 return NULL; 5 } else if (t->left == NULL) { 6 return t; 7 } else { 8 return FindMin(t->left); 9 } 10 }
查找最大值:從根開始,如果有右兒子,則向右進行。直到右兒子為空,則當前節點為最大值。

1 Position FindMax(SearchTree t) 2 { 3 if (t == NULL) { 4 return NULL; 5 } 6 7 while (t->right != NULL) 8 { 9 t = t->right; 10 } 11 return t; 12 }
這里查找最小值運用了遞歸,而查找最大值運用了非遞歸實現。
四、二叉搜索樹的插入
二叉搜索樹的插入過程和查找類似。新插入的節點一般在遍歷的路徑上的最后一點上,即葉子節點。如果待插入的數據比當前節點的數據大,並且當前節點的右兒子為空,則將待插入的節點插到右兒子位置上。如果右兒子不為空,則再遞歸的遍歷右兒子。如果小於當前節點,則對左兒子做類似的處理就行。

1 SearchTree Insert(ElementType x, SearchTree t) 2 { 3 if (t == NULL) { 4 /* 插入第一個節點 */ 5 t = (SearchTree)malloc(sizeof(struct TreeNode)); 6 if (t == NULL) { 7 return NULL; 8 } 9 t->element = x; 10 t->left = NULL; 11 t->right = NULL; 12 } else if (x < t->element) { 13 t->left = Insert(x, t->left); 14 } else if (x > t->element) { 15 t->right = Insert(x, t->right); 16 } 17 return t; 18 }
五、二叉搜索樹的刪除
二叉搜索樹的刪除分為以下幾個情況:
1、待刪除的節點是一個葉子節點,即它沒有左右兒子。此時只要將它的父節點指向NULL即可。
2、如果節點有一個兒子,則該節點可以在其父節點調整指針繞過該節點后刪除。
3、如果有兩個兒子,一般的刪除策略是用其右子樹中最小的數據代替該節點的數據並遞歸地刪除那個節點。因為右子樹中最小地節點不可能有左兒子(如果有,則說明不是最小的),所以第二次刪除更容易。(其實也就是將有兩個兒子的情況轉為容易處理的情況1或者2)。

1 /* 刪除策略 2 * 1、如果待刪除節點只有一個兒子,則將該節點的父節點的兒子節點指針指向該節點的兒子節點, 3 * 然后刪除該節點. 4 * 2、如果待刪除節點有兩個兒子,用右子樹中最小的數據代替該節點的數據並遞歸地刪除那個節點。 5 * 因為右子樹中最小地節點不可能有左兒子,所以第二次刪除更容易. 6 */ 7 SearchTree Delete(ElementType x, SearchTree t) 8 { 9 Position tmp; 10 if (t == NULL) { 11 return NULL; 12 } 13 if (x < t->element) { 14 t->left = Delete(x, t->left); 15 } else if (x > t->element) { 16 t->right = Delete(x, t->right); 17 } else if (t->left && t->right) { 18 tmp = FindMin(t->right); 19 t->element = tmp->element; 20 t->right = Delete(t->element, t->right); 21 } else { 22 tmp = t; 23 if (t->left) { 24 t = t->left; 25 } else if (t->right) { 26 t = t->right; 27 } 28 free(tmp); 29 tmp = NULL; 30 } 31 return t; 32 }
六、建立一棵空樹

1 SearchTree MakeEmpty(SearchTree t) 2 { 3 if (t != NULL) { 4 MakeEmpty(t->left); 5 MakeEmpty(t->right); 6 free(t); 7 t = NULL; 8 } 9 return NULL; 10 }
附錄:
完整代碼:

1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define ElementType int 5 struct TreeNode; 6 typedef struct TreeNode *Position; 7 typedef struct TreeNode *SearchTree; 8 9 SearchTree MakeEmpty(SearchTree t); 10 Position Find(ElementType x, SearchTree t); 11 Position FindMin(SearchTree t); 12 Position FindMax(SearchTree t); 13 SearchTree Insert(ElementType x, SearchTree t); 14 SearchTree Delete(ElementType x, SearchTree t); 15 16 struct TreeNode 17 { 18 ElementType element; 19 SearchTree left; 20 SearchTree right; 21 }; 22 23 SearchTree MakeEmpty(SearchTree t) 24 { 25 if (t != NULL) { 26 MakeEmpty(t->left); 27 MakeEmpty(t->right); 28 free(t); 29 t = NULL; 30 } 31 return NULL; 32 } 33 34 /* 查找以t為根節點的樹中,是否包含x */ 35 Position Find(ElementType x, SearchTree t) 36 { 37 if (t == NULL) { 38 return NULL; 39 } else if (x < t->element) { 40 return Find(x, t->left); 41 } else if (x > t->element) { 42 return Find(x, t->right); 43 } else { 44 return t; 45 } 46 } 47 48 Position FindMin(SearchTree t) 49 { 50 if (t == NULL) { 51 return NULL; 52 } else if (t->left == NULL) { 53 return t; 54 } else { 55 return FindMin(t->left); 56 } 57 } 58 59 Position FindMax(SearchTree t) 60 { 61 if (t == NULL) { 62 return NULL; 63 } 64 65 while (t->right != NULL) 66 { 67 t = t->right; 68 } 69 return t; 70 } 71 72 SearchTree Insert(ElementType x, SearchTree t) 73 { 74 if (t == NULL) { 75 /* 插入第一個節點 */ 76 t = (SearchTree)malloc(sizeof(struct TreeNode)); 77 if (t == NULL) { 78 return NULL; 79 } 80 t->element = x; 81 t->left = NULL; 82 t->right = NULL; 83 } else if (x < t->element) { 84 t->left = Insert(x, t->left); 85 } else if (x > t->element) { 86 t->right = Insert(x, t->right); 87 } 88 return t; 89 } 90 91 /* 刪除策略 92 * 1、如果待刪除節點只有一個兒子,則將該節點的父節點的兒子節點指針指向該節點的兒子節點, 93 * 然后刪除該節點. 94 * 2、如果待刪除節點有兩個兒子,用右子樹中最小的數據代替該節點的數據並遞歸地刪除那個節點。 95 * 因為右子樹中最小地節點不可能有左兒子,所以第二次刪除更容易. 96 */ 97 SearchTree Delete(ElementType x, SearchTree t) 98 { 99 Position tmp; 100 if (t == NULL) { 101 return NULL; 102 } 103 if (x < t->element) { 104 t->left = Delete(x, t->left); 105 } else if (x > t->element) { 106 t->right = Delete(x, t->right); 107 } else if (t->left && t->right) { 108 tmp = FindMin(t->right); 109 t->element = tmp->element; 110 t->right = Delete(t->element, t->right); 111 } else { 112 tmp = t; 113 if (t->left) { 114 t = t->left; 115 } else if (t->right) { 116 t = t->right; 117 } 118 free(tmp); 119 tmp = NULL; 120 } 121 return t; 122 } 123 124 void PrintfTree(SearchTree t) 125 { 126 if (t == NULL) { 127 return; 128 } 129 printf("%d ", t->element); 130 PrintfTree(t->left); 131 PrintfTree(t->right); 132 return; 133 } 134 135 int main() 136 { 137 ElementType i; 138 SearchTree binary_tree = NULL; 139 140 /******** Insert *********/ 141 for (i = 1; i < 11; i++) { 142 binary_tree = Insert(i, binary_tree); 143 } 144 PrintfTree(binary_tree); 145 printf("\n"); 146 147 /******** Find *********/ 148 Position pos = NULL; 149 pos = Find(6, binary_tree); 150 if (pos != NULL) { 151 printf("find %d\n", pos->element); 152 } else { 153 printf("Not find 6\n"); 154 } 155 pos = Find(11, binary_tree); 156 if (pos != NULL) { 157 printf("find %d\n", pos->element); 158 } else { 159 printf("Not find 11\n"); 160 } 161 162 /******** FindMin *********/ 163 Position min = NULL; 164 min = FindMin(binary_tree); 165 if (min) { 166 printf("find min, min: %d\n", min->element); 167 } else { 168 printf("not find min\n"); 169 } 170 171 /******** FindMax *********/ 172 Position max = NULL; 173 max = FindMax(binary_tree); 174 if (max) { 175 printf("find max, max: %d\n", max->element); 176 } else { 177 printf("not find max\n"); 178 } 179 180 181 Position del = NULL; 182 del = Delete(8, binary_tree); 183 PrintfTree(binary_tree); 184 printf("\n"); 185 186 binary_tree = MakeEmpty(binary_tree); 187 PrintfTree(binary_tree); 188 return 0; 189 }