查找(二叉排序树)
【1】二叉排序树
二叉排序树,又称为二叉查找树。
它或者是一棵空树,或者具有下列性质:
1. 若它的左子树不空,则左子树上所有的结点的值均小于它的根结点的值;
2. 若它的右子树不空,则右子树上所有的结点的值均大于它的根结点的值;
3. 它的左右子树也分别为二叉排序树。
【2】二叉排序树的代码实现
结合下图以及实现代码分析
(1)构建二叉排序树
(2)实现代码
1 #include <iostream> 2 using namespace std; 3 4 template<class Type> class BST; 5 6 template<class Type> 7 class BstNode 8 { 9 friend class BST<Type>; 10 Type data; 11 BstNode<Type> *leftChild, *rightChild; 12 public: 13 BstNode():leftChild(NULL), rightChild(NULL) 14 {} 15 BstNode(const Type &x,BstNode<Type> *left = NULL, BstNode<Type> *right = NULL) 16 : data(x) 17 , leftChild(left) 18 , rightChild(right) 19 {} 20 ~BstNode() 21 {} 22 Type & GetData() { return data;} 23 const Type & GetData() const { return data;} 24 BstNode<Type> *&GetLeft() { return leftChild;} 25 BstNode<Type> * const&GetLeft() const { return leftChild;} 26 BstNode<Type> * &GetRight() { return rightChild;} 27 BstNode<Type> * const &GetRight() const { return rightChild;} 28 }; 29 template<class Type> 30 class BST 31 { 32 private: 33 BstNode<Type> *root; 34 private: 35 ///////////////////////////////////私有方法部分 36 bool insert(BstNode<Type> *&ptr, const Type &x); 37 bool insertElem(BstNode<Type> *&ptr, const Type &x); 38 BstNode<Type>* find(BstNode<Type> * ptr, const Type &x); 39 BstNode<Type>* findRecursive(BstNode<Type> * ptr, const Type &x); 40 BstNode<Type>* findPre(BstNode<Type> *ptr, const Type &x); 41 BstNode<Type>* max(BstNode<Type> *ptr) const; 42 BstNode<Type>* min(BstNode<Type> *ptr) const; 43 bool remove(BstNode<Type> *&ptr, const Type &x); 44 bool removeRecursive(BstNode<Type> *&ptr, const Type &x); 45 void InOrder(BstNode<Type> *ptr) const; 46 void LevelOrder(BstNode<Type> *t) const; 47 public: 48 BST(): root(NULL) 49 { } 50 BST(Type x): root(NULL) 51 { } 52 ~BST() 53 { } 54 BstNode<Type>* GetRoot() 55 { 56 return root; 57 } 58 void SetRoot(BstNode<Type>* pRoot) 59 { 60 root = pRoot; 61 } 62 int Insert(const Type &x) 63 { 64 return insert(root, x); 65 } 66 BstNode<Type>* Find(const Type &x) 67 { 68 return find(root, x); 69 } 70 void InOrder() 71 { 72 InOrder(root); 73 cout << endl; 74 } 75 BstNode<Type>* Min() const 76 { 77 return min(root); 78 } 79 BstNode<Type> * Max() const 80 { 81 return max(root); 82 } 83 int Remove(const Type &x) 84 { 85 return remove(root, x); 86 } 87 void LevelOrder() 88 { 89 LevelOrder(root); 90 } 91 }; 92 // 插入数据元素方法1 (递归实现) 93 template<class Type> 94 bool BST<Type>::insert(BstNode<Type> *&ptr, const Type &x) 95 { 96 if (NULL == ptr) 97 { // 为空时就需要创建新节点 98 ptr = new BstNode<Type>(x); 99 if (NULL == ptr) 100 { 101 cerr << "out of space" << endl; 102 return false; 103 } 104 return true; 105 } 106 else if (x < ptr->data) 107 { // 小, 插入其左边 108 return insert(ptr->leftChild, x); 109 } 110 else if (x > ptr->data) 111 { // 大, 插入其右边 112 return insert(ptr->rightChild, x); 113 } 114 else 115 { // 两者相等 116 cout << "数据" << x << "重复,请重新输入..." << endl; 117 return false; 118 } 119 } 120 // 插入数据元素方法2 (非递归实现) 121 template<class Type> 122 bool BST<Type>::insertElem(BstNode<Type> *&ptr, const Type &x) 123 { 124 if (NULL == ptr) 125 { 126 ptr = new BstNode<Type>(x); 127 if (NULL == ptr) 128 { 129 cout << "out of space !" << endl; 130 return false; 131 } 132 return true; 133 } 134 BstNode<Type>* p = ptr, *q = NULL; 135 while (p != NULL) 136 { 137 q = p; 138 if (x == p->data) 139 { 140 cout << "数据重复" << endl; 141 return false; 142 } 143 if (x > p->data) 144 { 145 p = p->rightChild; 146 } 147 else if (x < p->data) 148 { 149 p = p->leftChild; 150 } 151 } 152 p = new BstNode<Type>(x); 153 if (x < q->data) 154 q->leftChild = p; 155 if (x > q->data) 156 q->rightChild = p; 157 return true; 158 } 159 // 查找某个数据元素的节点指针 (递归实现) 160 template<class Type> 161 BstNode<Type>* BST<Type>::findRecursive(BstNode<Type> *ptr, const Type &x) 162 { 163 if (NULL == ptr) 164 return NULL; 165 else if (x < ptr->data) 166 return find(ptr->leftChild, x); 167 else if (x > ptr->data) 168 return find(ptr->rightChild, x); 169 else 170 return ptr; 171 } 172 // 查找某个数据元素的节点指针 (非递归实现) 173 template<class Type> 174 BstNode<Type>* BST<Type>::find(BstNode<Type> *ptr, const Type &x) 175 { 176 while (ptr != NULL) 177 { 178 if (x == ptr->data) 179 return ptr; 180 else if (ptr->data > x) 181 ptr = ptr->leftChild; 182 else 183 ptr = ptr->rightChild; 184 } 185 return NULL; 186 } 187 // 查找某个数据元素的父节点指针 (非递归实现) 188 // 记录父节点,当孩子值与查找的数据元素值相同,返回父节点即可。 189 template<class Type> 190 BstNode<Type>* BST<Type>::findPre(BstNode<Type> *ptr, const Type &x) 191 { 192 BstNode<Type>* q = NULL; 193 while (ptr != NULL) 194 { 195 if (x == ptr->data) 196 { 197 return q; 198 } 199 else if (ptr->data > x) 200 { 201 q = ptr; 202 ptr = ptr->leftChild; 203 } 204 else 205 { 206 q = ptr; 207 ptr = ptr->rightChild; 208 } 209 } 210 return NULL; 211 } 212 // 按元素值删除某个节点 (递归实现) 213 // 具体删除思路请参考注释 214 template<class Type> 215 bool BST<Type>::removeRecursive(BstNode<Type> *&ptr, const Type &x) 216 { 217 BstNode<Type>* tmp = NULL; 218 if (ptr != NULL) 219 { 220 if (x < ptr->data) // 小于,转向左子树 221 return remove(ptr->leftChild, x); 222 else if (x > ptr->data) // 大于,转向右子树 223 return remove(ptr->rightChild, x); 224 // 相等时即找到 然后判断左右子树情况 225 else if (ptr->leftChild != NULL && ptr->rightChild != NULL) 226 { 227 // 1. 左右均不空 228 tmp = min(ptr->rightChild); // 找到右子树的最小值结点 229 ptr->data = tmp->data; // 数值更换 230 return remove(ptr->rightChild, ptr->data); // 递归再删除那个最小值结点 231 } 232 else 233 { // 2. 左为空 || 右为空 || 左右子树均为空 234 tmp = ptr; 235 if (NULL == ptr->leftChild) // 先考虑左子树 236 ptr = ptr->rightChild; // 衔接其右节点 237 else if (NULL == ptr->rightChild) // 再考虑右子树 238 ptr = ptr->leftChild; // 衔接其左节点 239 240 delete tmp; 241 tmp = NULL; 242 return true; 243 } 244 } 245 return false; 246 } 247 // 按元素值删除某个节点 (非递归实现) 248 // 具体删除思路请参考注释 249 template<class Type> 250 bool BST<Type>::remove(BstNode<Type> *&ptr, const Type &x) 251 { 252 BstNode<Type>* pself = find(ptr, x); // 欲删除结点自身 253 BstNode<Type>* parent = findPre(ptr, x); // 欲删除结点的父节点 254 BstNode<Type>* pDelete = pself; // 最终删除结点 255 if (NULL == pself) 256 { 257 cout << "删除数据不存在!" << endl; 258 return false; 259 } 260 // 满足以下情况时需要转换一下实际删除节点 261 if (pself->leftChild != NULL && pself->rightChild != NULL) 262 { 263 pDelete = min(pself->rightChild); // 找到右子树的最小值结点,将来删除它即可 264 pself->data = pDelete->data; // 数值更换 265 parent = findPre(pself->rightChild, pself->data); // 重新确定实际删除对象的父节点 266 if (NULL == parent) 267 { 268 // 当删除右子树的根节点 (只有可能右子树存在) 269 ptr->rightChild = pDelete->rightChild; // 衔接右子树即可 270 // 执行删除 释放内存 271 delete pDelete; 272 pDelete = NULL; 273 return true; 274 } 275 } 276 // 当欲删除父节点 且其孩子为空 277 if (NULL == parent) 278 { 279 if (NULL == pself->leftChild && 280 NULL == pself->rightChild) 281 { // 当树只有一个根节点 两孩子都为空 282 delete ptr; 283 ptr = NULL; 284 return true; 285 } 286 else if (NULL == pself->leftChild) 287 { // 右孩子存在 288 ptr = pself->rightChild; 289 } 290 else if (NULL == pself->rightChild) 291 { // 左孩子存在 292 ptr = pself->leftChild; 293 } 294 } 295 else 296 { 297 // 衔接结点 298 if (parent->data < pDelete->data) 299 { // 右孩子 300 if (NULL == pDelete->leftChild) 301 parent->rightChild = pDelete->rightChild; 302 else if (NULL == pDelete->rightChild) 303 parent->rightChild = pDelete->leftChild; 304 } 305 else 306 { // 左孩子 307 if (NULL == pDelete->leftChild) 308 parent->leftChild = pDelete->rightChild; 309 else if (NULL == pDelete->rightChild) 310 parent->leftChild = pDelete->leftChild; 311 } 312 } 313 // 执行删除 释放内存 314 delete pDelete; 315 pDelete = NULL; 316 return true; 317 } 318 // 打印二叉搜索树的数据 (中序遍历) 319 // 思路分析: 320 // 先遍历左子树 321 // 再遍历根节点 322 // 最后遍历右子树 323 template<class Type> 324 void BST<Type>::InOrder(BstNode<Type> *ptr) const 325 { 326 if (ptr != NULL) 327 { 328 InOrder(ptr->leftChild); 329 cout << ptr->data << " "; 330 InOrder(ptr->rightChild); 331 } 332 } 333 // 求二叉搜索树某一个子树的最小元素指针 334 // 思路分析: 335 // 一直向左子树递进即为最小 336 template<class Type> 337 BstNode<Type>* BST<Type>::min(BstNode<Type> *ptr) const 338 { 339 BstNode<Type> *p = ptr; 340 while (p != NULL && p->leftChild != NULL) 341 { 342 p = p->leftChild; 343 } 344 return p; 345 } 346 // 求二叉搜索树某一个子树的最大元素指针 347 // 思路分析: 348 // 一直向右子树递进即为最大 349 template<class Type> 350 BstNode<Type>* BST<Type>::max(BstNode<Type> *ptr) const 351 { 352 BstNode<Type> *p = ptr; 353 while (p != NULL && p->rightChild != NULL) // 保证p不等于空! 354 { 355 p = p->rightChild; 356 } 357 return p; 358 } 359 360 void main() 361 { 362 BST<int> bst; 363 int a[12] = {53,17,9,45,23,40,38,78,65,87,81,94}; 364 for (int i = 0; i < 12; ++i) 365 { 366 bst.Insert(a[i]); 367 } 368 cout << "中序遍历的结果如下:" << endl; 369 bst.InOrder(); 370 371 int data = 0; 372 cout << "请输入要查找的数据:"; 373 cin >> data; 374 if (bst.Find(data) != NULL) 375 cout << "查找成功!" << endl; 376 else 377 cout << "未查找到!" << endl; 378 379 cout << "请输入要删除的数据:"; 380 for (; ;) 381 { 382 int num = 0; 383 while (cin >> num, num != -1) 384 { 385 if (-1 == num) 386 break; 387 bst.Remove(num); 388 cout << "删除后数据打印:" << endl; 389 bst.InOrder(); 390 cout << "请输入要删除的数据(-1结束):"; 391 } 392 break; 393 } 394 }
Good Good Study, Day Day Up.
顺序 选择 循环 总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异