二叉树之二叉搜索树(BSTree)
Posted dua677
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树之二叉搜索树(BSTree)相关的知识,希望对你有一定的参考价值。
二叉搜索树(Binary Search Tree)
二叉搜索树是一种二叉树,子结点数量上限为2;为了方便搜索,结点是有序的,左结点的key不大于父节点,右节点的key不小于父节点,且左右子树也是二叉搜索树。
下面是一个二叉搜索树的样图,来自维基
一棵树一般都要提供一些函数,例如遍历、搜索、最大最小值、插入,删除,销毁等
代码含注释,下面是输出效果(msys2)
代码
开发环境:Qt Creator 4.8.2 Mingw64 7.3 windows 8.1
完整代码:https://github.com/Duacai/Data-Structure-and-Algorithms/tree/master/BSTree
Object.h
1 #ifndef OBJECT_H 2 #define OBJECT_H 3 4 #include <iomanip> // size_t 5 6 namespace LinWeiJie_lib 7 { 8 9 class Object 10 { 11 public: 12 void* operator new(size_t size); 13 void operator delete(void* p); 14 void* operator new[](size_t size); 15 void operator delete[](void* p); 16 bool operator == (const Object& obj); 17 bool operator != (const Object& obj); 18 virtual ~Object() = 0; 19 }; 20 21 } 22 23 #endif // OBJECT_H
Exception.h
1 #ifndef EXCEPTION_H 2 #define EXCEPTION_H 3 4 #include "Object.h" 5 6 namespace LinWeiJie_lib 7 { 8 9 #define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__)) // 注释掉throw语句即可兼容老版本的不支持异常处理的C++编译器 10 11 class Exception : public Object 12 { 13 protected: 14 char* m_message; 15 char* m_location; 16 17 void init(const char* message, const char* file, int line); 18 public: 19 Exception(const char* message); 20 Exception(const char* file, int line); 21 Exception(const char* message, const char* file, int line); 22 23 Exception(const Exception& e); 24 Exception& operator= (const Exception& e); 25 26 virtual const char* message() const; 27 virtual const char* location() const; 28 29 virtual ~Exception() = 0; 30 }; 31 32 class ArithmeticException : public Exception // 算术异常 33 { 34 public: 35 ArithmeticException() : Exception(nullptr){} 36 ArithmeticException(const char* message) : Exception(message){} 37 ArithmeticException(const char* file, int line) : Exception(file, line){} 38 ArithmeticException(const char* message, const char* file, int line) : Exception(message, file, line){} 39 40 ArithmeticException(const ArithmeticException& e) : Exception(e){} 41 42 ArithmeticException& operator=(const ArithmeticException& e) 43 { 44 Exception::operator=(e); 45 46 return *this; 47 } 48 49 ~ArithmeticException(); 50 }; 51 52 class NullPointerException : public Exception // 空指针异常 53 { 54 public: 55 NullPointerException() : Exception(nullptr) {} 56 NullPointerException(const char* message) : Exception(message) {} 57 NullPointerException(const char* file, int line) : Exception(file, line) {} 58 NullPointerException(const char* message, const char* file, int line) : Exception(message, file, line) {} 59 60 NullPointerException(const NullPointerException& e) : Exception(e) {} 61 62 NullPointerException& operator= (const NullPointerException& e) 63 { 64 Exception::operator=(e); 65 66 return *this; 67 } 68 69 ~NullPointerException(); 70 }; 71 72 class IndexOutOfBoundsException : public Exception // 下标越界异常 73 { 74 public: 75 IndexOutOfBoundsException() : Exception(nullptr) {} 76 IndexOutOfBoundsException(const char* message) : Exception(message) {} 77 IndexOutOfBoundsException(const char* file, int line) : Exception(file, line) {} 78 IndexOutOfBoundsException(const char* message, const char* file, int line) : Exception(message, file, line) {} 79 80 IndexOutOfBoundsException(const IndexOutOfBoundsException& e) : Exception(e) {} 81 82 IndexOutOfBoundsException& operator= (const IndexOutOfBoundsException& e) 83 { 84 Exception::operator=(e); 85 86 return *this; 87 } 88 89 ~IndexOutOfBoundsException(); 90 }; 91 92 class NoEnoughMemoryException : public Exception // 内存不足异常 93 { 94 public: 95 NoEnoughMemoryException() : Exception(nullptr) {} 96 NoEnoughMemoryException(const char* message) : Exception(message) {} 97 NoEnoughMemoryException(const char* file, int line) : Exception(file, line) {} 98 NoEnoughMemoryException(const char* message, const char* file, int line) : Exception(message, file, line) {} 99 100 NoEnoughMemoryException(const NoEnoughMemoryException& e) : Exception(e) {} 101 102 NoEnoughMemoryException& operator= (const NoEnoughMemoryException& e) 103 { 104 Exception::operator=(e); 105 106 return *this; 107 } 108 109 ~NoEnoughMemoryException(); 110 }; 111 112 class InvalidParameterException : public Exception // 无效参数异常 113 { 114 public: 115 InvalidParameterException() : Exception(nullptr) {} 116 InvalidParameterException(const char* message) : Exception(message) {} 117 InvalidParameterException(const char* file, int line) : Exception(file, line) {} 118 InvalidParameterException(const char* message, const char* file, int line) : Exception(message, file, line) {} 119 120 InvalidParameterException(const InvalidParameterException& e) : Exception(e) {} 121 122 InvalidParameterException& operator= (const InvalidParameterException& e) 123 { 124 Exception::operator=(e); 125 126 return *this; 127 } 128 129 ~InvalidParameterException(); 130 }; 131 132 class InvalidOperationException : public Exception // 无效操作异常 133 { 134 public: 135 InvalidOperationException() : Exception(nullptr) {} 136 InvalidOperationException(const char* message) : Exception(message) {} 137 InvalidOperationException(const char* file, int line) : Exception(file, line) {} 138 InvalidOperationException(const char* message, const char* file, int line) : Exception(message, file, line) {} 139 140 InvalidOperationException(const InvalidOperationException& e) : Exception(e) {} 141 142 InvalidOperationException& operator= (const InvalidOperationException& e) 143 { 144 Exception::operator=(e); 145 146 return *this; 147 } 148 149 ~InvalidOperationException(); 150 }; 151 152 class DuplicateDataException : public Exception // 重复数据异常 153 { 154 public: 155 DuplicateDataException() : Exception(nullptr) {} 156 DuplicateDataException(const char* message) : Exception(message) {} 157 DuplicateDataException(const char* file, int line) : Exception(file, line) {} 158 DuplicateDataException(const char* message, const char* file, int line) : Exception(message, file, line) {} 159 160 DuplicateDataException(const DuplicateDataException& e) : Exception(e) {} 161 162 DuplicateDataException& operator= (const DuplicateDataException& e) 163 { 164 Exception::operator=(e); 165 166 return *this; 167 } 168 169 ~DuplicateDataException(); 170 }; 171 172 class FileOversizeException : public Exception // 文件太大异常 173 { 174 public: 175 FileOversizeException() : Exception(nullptr) {} 176 FileOversizeException(const char* message) : Exception(message) {} 177 FileOversizeException(const char* file, int line) : Exception(file, line) {} 178 FileOversizeException(const char* message, const char* file, int line) : Exception(message, file, line) {} 179 180 FileOversizeException(const FileOversizeException& e) : Exception(e) {} 181 182 FileOversizeException& operator= (const FileOversizeException& e) 183 { 184 Exception::operator=(e); 185 186 return *this; 187 } 188 189 ~FileOversizeException(); 190 }; 191 192 class EmptyTreeException : public Exception // 空树异常 193 { 194 public: 195 EmptyTreeException() : Exception(nullptr) {} 196 EmptyTreeException(const char* message) : Exception(message) {} 197 EmptyTreeException(const char* file, int line) : Exception(file, line) {} 198 EmptyTreeException(const char* message, const char* file, int line) : Exception(message, file, line) {} 199 200 EmptyTreeException(const EmptyTreeException& e) : Exception(e) {} 201 202 EmptyTreeException& operator= (const EmptyTreeException& e) 203 { 204 Exception::operator=(e); 205 206 return *this; 207 } 208 209 ~EmptyTreeException(); 210 }; 211 212 } 213 214 #endif // EXCEPTION_H
Tree.h
1 #ifndef TREE_H 2 #define TREE_H 3 4 #include <iomanip> 5 6 namespace LinWeiJie_lib 7 { 8 9 template < typename T > 10 class TNode 11 { 12 public: 13 T mKey; 14 15 TNode() = delete; 16 TNode(const T& key); 17 TNode(const TNode<T>& tNode) = default; 18 TNode(TNode<T> && tNode) = default; 19 TNode<T>& operator = (const TNode<T>& tNode) = default; 20 TNode<T>& operator = (TNode<T> && tNode) = default; 21 virtual ~TNode() = 0; 22 }; 23 24 template < typename T > 25 TNode<T>::TNode(const T& key) : mKey(key) 26 { 27 } 28 29 template < typename T > 30 TNode<T>::~TNode() 31 { 32 } 33 34 template < typename T > 35 class Tree 36 { 37 protected: 38 TNode<T>* mRoot; 39 size_t mCount; 40 41 Tree(); 42 Tree(const Tree<T>& tree) = delete; 43 Tree(Tree<T> && tree); 44 Tree<T>& operator = (const Tree<T>& tree) = delete; 45 Tree<T>& operator = (Tree<T> && tree); 46 virtual ~Tree() = 0; 47 48 public: 49 virtual void preOrder() const = 0; 50 virtual void inOrder() const = 0; 51 virtual void postOrder() const = 0; 52 virtual void levelOrder() const = 0; 53 54 virtual TNode<T>* search(const T& key) const = 0; // 递归版 55 virtual TNode<T>* iterativeSearch(const T& key) const = 0; // 非递归版 56 57 virtual void insert(const T& node) = 0; 58 virtual void remove(const T& node) = 0; 59 virtual void destroy() = 0; 60 61 virtual const T& getRootKey() const = 0; 62 virtual void printTree() const = 0; 63 }; 64 65 template < typename T > 66 Tree<T>::Tree() : mRoot(nullptr), mCount(0) 67 { 68 } 69 70 template < typename T > 71 Tree<T>::Tree(Tree<T> && tree) 72 { 73 mRoot = tree.mRoot; 74 mCount = tree.mCount; 75 76 tree.mRoot = nullptr; 77 tree.mCount = 0; 78 } 79 80 template < typename T > 81 Tree<T>& Tree<T>::operator = (Tree<T> && tree) 82 { 83 if ( this == &tree ) 84 return *this; 85 86 mRoot = tree.mRoot; 87 mCount = tree.mCount; 88 89 tree.mRoot = nullptr; 90 tree.mCount = 0; 91 } 92 93 template < typename T > 94 Tree<T>::~Tree() 95 { 96 } 97 98 } 99 100 #endif
BSTree.h
1 #ifndef BSTREE_H 2 #define BSTREE_H 3 4 #include <iostream> 5 #include <stack> 6 #include <queue> 7 8 #include "Exception.h" 9 #include "Tree.h" 10 11 using namespace std; 12 13 namespace LinWeiJie_lib 14 { 15 16 template < typename T > 17 class BSTNode : public TNode<T> 18 { 19 public: 20 BSTNode<T> *mLeft; 21 BSTNode<T> *mRight; 22 BSTNode<T> *mParent; 23 24 BSTNode() = delete; 25 BSTNode(const T& key, BSTNode<T> *left, BSTNode<T> *right, BSTNode<T> *parent); 26 BSTNode(const BSTNode<T>& tree) = delete; 27 BSTNode(BSTNode<T> && tree); 28 BSTNode<T>& operator = (const BSTNode<T>& tree) = delete; 29 BSTNode<T>& operator = (BSTNode<T> && tree); 30 virtual ~BSTNode(); 31 }; 32 33 template < typename T > 34 BSTNode<T>::BSTNode(const T& key, BSTNode<T> *left, BSTNode<T> *right, BSTNode<T> *parent) : 35 TNode<T> (key), mLeft(left), mRight(right), mParent(parent) 36 { 37 } 38 39 template < typename T > 40 BSTNode<T>::BSTNode(BSTNode<T> && tree) 41 { 42 mLeft = tree.mLeft; 43 mRight = tree.mRight; 44 mParent = tree.mParent; 45 46 tree->mLeft = nullptr; 47 tree->mRight = nullptr; 48 tree->mParent = nullptr; 49 } 50 51 template < typename T > 52 BSTNode<T>& BSTNode<T>::operator = (BSTNode<T> && tree) 53 { 54 if ( this == &tree ) 55 return *this; 56 57 delete mLeft; 58 delete mRight; 59 delete mParent; 60 61 mLeft = tree->mLeft; 62 mRight = tree->mRight; 63 mParent = tree->mParent; 64 65 return *this; 66 } 67 68 template < typename T > 69 BSTNode<T>::~BSTNode() 70 { 71 72 } 73 74 template < typename T > 75 class BSTree : public Tree<T> 76 { 77 protected: 78 virtual void preOrder(BSTNode<T> *tree) const; // 深度优先的前、中、后序遍历 79 virtual void inOrder(BSTNode<T> *tree) const; 80 virtual void postOrder(BSTNode<T> *tree) const; 81 82 virtual void levelOrder(BSTNode<T> *tree) const; // 广度优先 83 84 virtual BSTNode<T>* search(BSTNode<T> *tree, const T& key) const; // 递归版搜索 85 virtual BSTNode<T>* iterativeSearch(BSTNode<T> *tree, const T& key) const; // 非递归版搜索 86 87 virtual BSTNode<T>* minimum(BSTNode<T> *tree) const; // 获取最小最大值 88 virtual BSTNode<T>* maximum(BSTNode<T> *tree) const; 89 90 virtual BSTNode<T>* successor(BSTNode<T> *node) const; // 查找后继,即大于又最接近node的节点 91 virtual BSTNode<T>* predecessor(BSTNode<T> *node) const; // 查找前继 92 93 virtual void insert(BSTNode<T> *node); 94 virtual BSTNode<T>* remove(BSTNode<T> *node); // 返回值用于删除,返回值实际是替换结点 95 virtual void destroy(BSTNode<T> *tree); 96 97 void printTree(BSTNode<T> *tree, bool firstNode) const; // 打印树,类似linux的tree命令 98 99 virtual int height(BSTNode<T> *tree) const; // 树的高度 100 virtual int degree(BSTNode<T> *tree) const; // 结点的度数 101 102 public: 103 BSTree(); 104 BSTree(const BSTree<T>&) = default; 105 BSTree(BSTree<T> &&) = default; 106 BSTree<T>& operator = (const BSTree<T>&) = default; 107 BSTree<T>& operator = (BSTree<T> &&) = default; 108 virtual ~BSTree(); 109 110 virtual void preOrder() const; 111 virtual void inOrder() const; 112 virtual void postOrder() const; 113 114 virtual void levelOrder() const; 115 116 virtual BSTNode<T>* search(const T& key) const; 117 virtual BSTNode<T>* iterativeSearch(const T& key) const; 118 119 virtual const T& minimum() const; 120 virtual const T& maximum() const; 121 122 virtual void insert(const T& key); 123 virtual void remove(const T& key); 124 virtual void destroy(); 125 126 virtual int height() const; 127 virtual int degree() const; 128 129 virtual size_t getCount() const; 130 131 virtual const T& getRootKey() const; 132 virtual void printTree() const; 133 }; 134 135 template < typename T > 136 BSTree<T>::BSTree() : Tree<T> () 137 { 138 } 139 140 template < typename T > 141 void BSTree<T>::preOrder(BSTNode<T> *tree) const 142 { 143 if ( tree != nullptr ) 144 { 145 cout << tree->mKey << " " << flush; 146 preOrder(tree->mLeft); 147 preOrder(tree->mRight); 148 } 149 } 150 151 template < typename T > 152 void BSTree<T>::preOrder() const 153 { 154 preOrder(dynamic_cast<BSTNode<T>*>(this->mRoot)); 155 } 156 157 template < typename T > 158 void BSTree<T>::inOrder(BSTNode<T> *tree) const 159 { 160 if ( tree != nullptr ) 161 { 162 inOrder(tree->mLeft); 163 cout << tree->mKey << " " << flush; 164 inOrder(tree->mRight); 165 } 166 } 167 168 template < typename T > 169 void BSTree<T>::inOrder() const 170 { 171 inOrder(dynamic_cast<BSTNode<T>*>(this->mRoot)); 172 } 173 174 template < typename T > 175 void BSTree<T>::postOrder(BSTNode<T> *tree) const 176 { 177 if ( tree != nullptr ) 178 { 179 postOrder(tree->mLeft); 180 postOrder(tree->mRight); 181 cout << tree->mKey << " " << flush; 182 } 183 } 184 185 template < typename T > 186 void BSTree<T>::postOrder() const 187 { 188 postOrder(dynamic_cast<BSTNode<T>*>(this->mRoot)); 189 } 190 191 template < typename T > 192 void BSTree<T>::levelOrder(BSTNode<T> *tree) const 193 { 194 if ( tree != nullptr ) 195 { 196 queue<BSTNode<T>*> tmp; 197 tmp.push(tree); 198 199 while( tmp.size() > 0 ) 200 { 201 BSTNode<T>* t = tmp.front(); 202 tmp.pop(); 203 204 if ( t->mLeft != nullptr ) 205 tmp.push(t->mLeft); 206 207 if ( t->mRight != nullptr ) 208 tmp.push(t->mRight); 209 210 cout << t->mKey << " " << flush; 211 } 212 } 213 } 214 215 template < typename T > 216 void BSTree<T>::levelOrder() const 217 { 218 levelOrder(dynamic_cast<BSTNode<T>*>(this->mRoot)); 219 } 220 221 template < typename T > 222 BSTNode<T>* BSTree<T>::search(BSTNode<T> *node, const T& key) const 223 { 224 if ( node == nullptr || node->mKey == key ) 225 { 226 return node; 227 } 228 else if ( key < node->mKey ) 229 return search(dynamic_cast<BSTNode<T>*>(node)->mLeft, key); 230 else 231 return search(dynamic_cast<BSTNode<T>*>(node)->mRight, key); 232 } 233 234 template < typename T > 235 BSTNode<T>* BSTree<T>::search(const T& key) const 236 { 237 return search(dynamic_cast<BSTNode<T>*>(this->mRoot), key); 238 } 239 240 template < typename T > 241 BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* node, const T& key) const 242 { 243 while ( (node != nullptr) && (node->mKey != key) ) 244 { 245 if ( key < node->mKey ) 246 node = node->mLeft; 247 else 248 node = node->mRight; 249 } 250 251 return node; 252 } 253 254 template < typename T > 255 BSTNode<T>* BSTree<T>::iterativeSearch(const T& value) const 256 { 257 return iterativeSearch(dynamic_cast<BSTNode<T>*>(this->mRoot), value); 258 } 259 260 template < typename T > 261 BSTNode<T>* BSTree<T>::minimum(BSTNode<T>* tree) const 262 { 263 if ( tree == nullptr ) 264 return nullptr; 265 266 while ( tree->mLeft != nullptr ) 267 tree = tree->mLeft; 268 269 return tree; 270 } 271 272 template < typename T > 273 const T& BSTree<T>::minimum() const 274 { 275 BSTNode<T> *p = minimum(dynamic_cast<BSTNode<T>*>(this->mRoot)); 276 if ( p == nullptr ) 277 THROW_EXCEPTION(EmptyTreeException, "The tree is empty ..."); 278 279 return p->mKey; 280 } 281 282 template < typename T > 283 BSTNode<T>* BSTree<T>::maximum(BSTNode<T>* tree) const 284 { 285 if ( tree == nullptr ) 286 return nullptr; 287 288 while ( tree->mRight != nullptr ) 289 tree = tree->mRight; 290 291 return tree; 292 } 293 294 template < typename T > 295 const T& BSTree<T>::maximum() const 296 { 297 BSTNode<T> *p = maximum(dynamic_cast<BSTNode<T>*>(this->mRoot)); 298 if ( p == nullptr ) 299 THROW_EXCEPTION(EmptyTreeException, "The tree is empty ..."); 300 301 return p->mKey; 302 } 303 304 template < typename T > 305 BSTNode<T>* BSTree<T>::successor(BSTNode<T> *node) const // 查找后继 306 { 307 if ( node->mRight != nullptr ) // 如果node有右孩子,则在它的右孩子里面最小的是后继 308 { 309 return minimum(node->mRight); 310 } 311 312 BSTNode<T>* ret = node->mParent; // 如果node没有右孩子,且它自身是左孩子,则它的父亲是后继 313 while ( (ret != nullptr) && (node == ret->mRight) ) // 如果node没有右孩子,且它自身是右孩子,它的最近祖先是左孩子的,则这个祖先的父亲就是后继 314 { 315 node = ret; 316 ret = ret->mParent; 317 } 318 319 return ret; 320 } 321 322 template < typename T > 323 BSTNode<T>* BSTree<T>::predecessor(BSTNode<T>* node) const // 查找前继 324 { 325 if ( node->mLeft != nullptr ) // 如果node有左孩子,则在它的左孩子里面最大的是前继 326 return maximum(node->mLeft); 327 328 BSTNode<T>* ret = node->mParent; // 如果node没有左孩子,且它自身是右孩子,则它的父亲是后继 329 while ( (ret != nullptr) && (node == ret->mLeft) ) // 如果node没有左孩子,且它自身是左孩子,它的最近祖先是右孩子的,则这个祖先的父亲就是后继 330 { 331 node = ret; 332 ret = ret->mLeft; 333 } 334 335 return ret; 336 } 337 338 template < typename T > 339 void BSTree<T>::insert(BSTNode<T>* node) 340 { 341 BSTNode<T>* in = nullptr; // 插入点 342 BSTNode<T>* parent = dynamic_cast<BSTNode<T>*>(this->mRoot); // 插入点的父节点 343 344 while ( parent != nullptr ) // 查找node的插入点 345 { 346 in = parent; 347 if ( node->mKey < in->mKey ) // 如果node结点小于插入点,则插入到左孩子分支 348 parent = parent->mLeft; 349 else if ( node->mKey > in->mKey ) // 如果node结点大于插入点,则插入到右孩子分支 350 parent = parent->mRight; 351 else // 如果数据等同则跳出 352 break; 353 } 354 355 node->mParent = in; // 设置node结点的父亲为插入点 356 if ( in == nullptr ) // 如果插入点为空,设node结点为根节点 357 this->mRoot = node; 358 else if ( node->mKey < in->mKey ) // 如果node结点小于插入点,插入左边 359 in->mLeft = node; 360 else if ( node->mKey > in->mKey ) // 如果node结点大于插入点,插入右边 361 in->mRight = node; 362 else // 如果数据等同则直接替换并释放插入的结点 363 { 364 in->mKey = node->mKey; 365 delete node; 366 return; 367 } 368 369 ++this->mCount; // 结点统计,注意重复结点插入时不能增加 370 } 371 372 template < typename T > 373 void BSTree<T>::insert(const T& key) 374 { 375 insert(new BSTNode<T>(key, nullptr, nullptr, nullptr)); 376 } 377 378 template < typename T > 379 BSTNode<T>* BSTree<T>::remove(BSTNode<T> *node) 380 { 381 BSTNode<T>* replace = nullptr; // 代替结点 382 BSTNode<T>* del = nullptr; // 删除点 383 384 if ( (node->mLeft == nullptr) || (node->mRight == nullptr) ) // 如果孩子不全,node就是删除点,可以直接用仅有的孩子代替 385 del = node; 386 else // 否则有两个孩子,后继就是删除点(右子树中最小的成员) 387 { 388 del = successor(node); // 查找后继 389 node->mKey = del->mKey; // 直接用后继key替换node的key 390 } 391 392 if ( del->mLeft != nullptr ) // 如果有左孩子,则更新左孩子为代替结点(如果if成立就只有左孩子) 393 replace = del->mLeft; 394 else // 否则设右孩子为代替结点 395 replace = del->mRight; 396 397 if ( replace != nullptr ) // 如果代替结点不是空树,更新代替结点的父亲 398 replace->mParent = del->mParent; 399 400 if ( del->mParent == nullptr ) // 如果结点是根节点且孩子不全,那就直接替换 401 this->mRoot = replace; 402 else if ( del == del->mParent->mLeft ) // 如果删除点为左孩子,则更新父节点的左孩子 403 del->mParent->mLeft = replace; 404 else // 否则更新父节点的右孩子 405 del->mParent->mRight = replace; 406 407 --this->mCount; 408 409 return del; 410 } 411 412 template < typename T > 413 void BSTree<T>::remove(const T& key) 414 { 415 BSTNode<T> *del = nullptr, *node; 416 del = search(dynamic_cast<BSTNode<T>*>(this->mRoot), key); 417 418 if ( del != nullptr ) // 找到的删除点不为空 419 if ( (node = remove(del)) != nullptr ) // 删除node并返回代替结点 420 delete node; // 删除代替结点 421 } 422 423 template < typename T > 424 void BSTree<T>::destroy(BSTNode<T> *tree) 425 { 426 if ( tree == nullptr ) 427 return; 428 429 if ( tree->mLeft != nullptr ) 430 destroy(tree->mLeft); 431 432 if ( tree->mRight != nullptr ) 433 destroy(tree->mRight); 434 435 delete tree; 436 tree = nullptr; 437 } 438 439 template < typename T > 440 void BSTree<T>::destroy() 441 { 442 destroy(dynamic_cast<BSTNode<T>*>(this->mRoot)); 443 this->mRoot = nullptr; 444 this->mCount = 0; 445 } 446 447 template < typename T > 448 int BSTree<T>::height(BSTNode<T>* node) const 449 { 450 int ret = 0; 451 452 if( node != nullptr ) 453 { 454 int lh = height(node->mLeft); 455 int rh = height(node->mRight); 456 457 ret = ((lh > rh) ? lh : rh) + 1; 458 } 459 460 return ret; 461 } 462 463 template < typename T > 464 int BSTree<T>::height() const 465 { 466 int ret = 0; 467 468 if( this->mRoot != nullptr ) 469 { 470 ret = height(dynamic_cast<BSTNode<T>*>(this->mRoot)); 471 } 472 473 return ret; 474 } 475 476 template < typename T > 477 int BSTree<T>::degree(BSTNode<T>* node) const 478 { 479 int ret = 0; 480 481 if( node != nullptr ) 482 { 483 BSTNode<T>* child[] = { node->mLeft, node->mRight }; 484 485 ret = (!!node->mLeft + !!node->mRight); // 统计有效结点数,!!用于转换成bool类型,如果是有效结点则为1,否则为0 486 487 for(int i=0; (i<2) && (ret<2); i++) // 如果儿子不足2个需要检查 488 { 489 int d = degree(child[i]); 490 491 if( ret < d ) 492 { 493 ret = d; 494 } 495 } 496 } 497 498 return ret; 499 } 500 501 template < typename T > 502 int BSTree<T>::degree() const 503 { 504 return degree(dynamic_cast<BSTNode<T>*>(this->mRoot)); 505 } 506 507 template < typename T > 508 size_t BSTree<T>::getCount() const 509 { 510 return this->mCount; 511 } 512 513 template <typename T> 514 void BSTree<T>::printTree(BSTNode<T> *tree, bool firstNode) const 515 { 516 if ( tree == nullptr ) 517 return; 518 519 size_t height = this->height(); // 树的高度 520 static bool *outTag = new bool[height](); // 左边是否还有结点的标记,初始化为false 521 uint8_t static layer = 0; // 当前层数,根结点为第一层 522 uint8_t i; 523 ++layer; 524 525 if ( layer > 1 ) // 如果不是根节点需要输出特殊符号 526 { 527 for (i=1; i<layer-1; ++i ) // 根节点和最后一个结点不需要,所以从1至(layer-1) 528 if ( outTag[i] ) // 如果左边还有结点 529 cout << "| "; 530 else 531 cout << " "; 532 533 if ( firstNode == true ) // 判断左右结点,非二叉树需要另外处理 534 cout << "L-------" << flush; 535 else 536 cout << "R-------" << flush; 537 } 538 cout << tree->mKey << endl; 539 540 if ( (tree->mRight) != nullptr ) // 先输出右节点 541 { 542 if ( tree->mLeft != nullptr ) // 如果左边还有结点需要做标记 543 outTag[layer] = true; 544 printTree(tree->mRight, false); // false表示当前是右节点 545 } 546 547 if ( tree->mLeft != nullptr ) 548 { 549 outTag[layer] = false; // 左结点左边不再有结点,恢复默认标记 550 printTree(tree->mLeft, true); 551 } 552 553 --layer; // 结点回溯时高度需要减1 554 } 555 556 template <typename T> 557 void BSTree<T>::printTree() const 558 { 559 printTree(dynamic_cast<BSTNode<T>*>(this->mRoot), false); // 作为根节点时,右参数无意义 560 } 561 562 template < typename T > 563 const T& BSTree<T>::getRootKey() const 564 { 565 return this->mRoot->mKey; 566 } 567 568 template < typename T > 569 BSTree<T>::~BSTree() 570 { 571 destroy(); 572 } 573 574 } 575 576 #endif // BSTREE_H
Times.h
1 #ifndef TIMES_H 2 #define TIMES_H 3 4 #include <iostream> 5 #include <sys/time.h> 6 #ifdef _WIN32 7 #include <windows.h> 8 #endif 9 10 namespace LinWeiJie_lib 11 { 12 13 // CPU频率计时器 14 #if defined (__i386__) 15 static __inline__ unsigned long long GetCycleCount(void) 16 { 17 unsigned long long int x; 18 __asm__ volatile("rdtsc":"=A"(x)); 19 return x; 20 } 21 #elif defined (__x86_64__) 22 static __inline__ unsigned long long GetCycleCount(void) 23 { 24 unsigned hi,lo; 25 __asm__ volatile("rdtsc":"=a"(lo),"=d"(hi)); 26 return (static_cast<unsigned long long>(lo))|(static_cast<unsigned long long>(hi)<<32); 27 } 28 #endif 29 30 static void timing(bool b){ 31 if(b) goto GET; 32 static struct timeval tv_begin, tv_end; 33 gettimeofday(&tv_begin, nullptr); 34 35 #ifdef _WIN32 36 static LARGE_INTEGER li_freq, li_start, li_stop; 37 QueryPerformanceFrequency(&li_freq); 38 QueryPerformanceCounter(&li_start); 39 #endif 40 41 static uint64_t t1 = GetCycleCount(); 42 43 std::cout << "启动计时..." << std::endl; 44 goto END; 45 46 GET: 47 gettimeofday(&tv_end, nullptr); 48 std::cout << "Linux: \\t" << std::fixed << (tv_end.tv_sec+tv_end.tv_usec/1000000.0)-(tv_begin.tv_sec+tv_begin.tv_usec/1000000.0) << " s" << std::endl; 49 50 #ifdef _WIN32 51 QueryPerformanceCounter(&li_stop); 52 std::cout << "Windows:\\t" << (li_stop.QuadPart-li_start.QuadPart) * 1.0 / li_freq.QuadPart << " s" << std::endl; 53 #endif 54 55 std::cout << "CPU: \\t" << (GetCycleCount() - t1)/3800000000.0 << " s" << std::endl; 56 END: 57 ; 58 } 59 60 static void timingStart() 61 { 62 timing(false); 63 } 64 65 static void timingEnd() 66 { 67 timing(true); 68 } 69 70 } 71 72 #endif // TIMES_H
main.cpp
1 #include <iostream> 2 #include <cmath> 3 4 #include "BSTree.h" 5 6 #include "Times.h" 7 8 using namespace std; 9 using namespace LinWeiJie_lib; 10 11 int main(int argc, char* argv[]) 12 { 13 uint16_t layer = 8; // 结点最小层数 14 15 if ( argc == 2 && atoi(argv[1])>0 ) 16 layer = static_cast<uint8_t>(atoi(argv[1])); 17 else { 18 cout << "请输入结点最小层数,注意内存大小,结点层数上限为:" << log(RAND_MAX*RAND_MAX+1)/log(2) << endl; 19 cin >> layer; 20 } 21 22 timingStart(); // 启动计时 23 24 cout << endl; 25 26 uint64_t const count = (1ull<<layer)-1; // 结点数 27 uint16_t speed; // 记录插入和删除的进度百分比(0~100) 28 29 BSTree<uint64_t> *tree = new BSTree<uint64_t>(); 30 31 speed = 0; 32 srand(static_cast<unsigned int>(time(nullptr))); 33 while ( tree->getCount() < count ) 34 { 35 tree->insert(static_cast<size_t>(rand()*rand())); // 使用随机值插入;如果是顺序值,会退化成链表模式,且插入变慢 36 37 if ( (tree->getCount()*100/count > speed) || (tree->getCount() == count) ) // 进度值出现变化或完成操作时才能输出 38 { 39 speed = static_cast<uint16_t>(tree->getCount()*100/count); 40 cout << "\\r已添加:" << setw(3) << speed << ‘%‘ << flush; 41 } 42 } 43 cout << endl; 44 45 cout << "\\n前序遍历: "; 46 tree->preOrder(); 47 cout << endl; 48 49 cout << "\\n中序遍历: "; 50 tree->inOrder(); 51 cout << endl; 52 53 cout << "\\n后续遍历: "; 54 tree->postOrder(); 55 cout << endl; 56 57 cout << "\\n广度遍历:"; 58 tree->levelOrder(); 59 cout << endl; 60 61 cout << "\\n最小值: " << tree->minimum(); 62 cout << "\\n最大值: " << tree->maximum(); 63 cout << "\\nheight = " << tree->height(); 64 cout << "\\n结点数= " << tree->getCount(); 65 cout << endl; 66 67 cout << "\\n输出树形信息:" << endl; 68 tree->printTree(); 69 cout << endl; 70 71 speed = 0; 72 srand(static_cast<unsigned int>(time(nullptr))); 73 while ( tree->getCount() ) 74 { 75 uint64_t node; 76 // if ( tree->getCount()*100/count < 20 ) // 剩余量太少时,随机值命中有效结点的概率太低,从而导致删除缓慢 77 node = tree->getRootKey(); 78 // else 79 // node = static_cast<size_t>(rand()*rand()); 80 81 tree->remove(node); 82 83 if ( ((count-tree->getCount())*100/count > speed) || (tree->getCount() == count) ) 84 { 85 speed = static_cast<uint16_t>((count-tree->getCount())*100/count); 86 cout << "\\r已删除:" << setw(3) << speed << ‘%‘ << flush; 87 } 88 } 89 cout << endl; 90 91 tree->destroy(); 92 delete tree; 93 tree = nullptr; 94 95 cout << endl; 96 timingEnd(); 97 98 return 0; 99 }
以上是关于二叉树之二叉搜索树(BSTree)的主要内容,如果未能解决你的问题,请参考以下文章