C++ 二叉搜索树原理及其实现

首先是概念:
二叉搜索树又称二叉排序树,它具有以下的性质:

  • 若是左子树不为空,则左子树上所有节点的值小于根节点的值
  • 若是右子树不为空,则右子树上所有结点的值大于根节点的值
  • 二叉搜索树的左右子树也是二叉搜索树
  • 二叉搜索树的中序排列是一个有序数列

再下来是它的实现

首先是构造节点

 1 template<class K>
 2 struct BStreeNode{
 3     BStreeNode(const K& date = K())    //节点的定义
 4     :leftC(nullptr),    // 初始化
 5     rightC(nullptr),
 6     date_(date)
 7     {}
 8     BStreeNode<K> *leftC;      //左孩子
 9     BStreeNode<K> *rightC;    //右孩子
10     K date_;
11 };

然后是类的实现(具体细节都标在了注释里):

  1 template<class K>
  2 class BStree{
  3     typedef BStreeNode<K> BsNode;
  4 public:
  5     BStree() :
  6         _root(nullptr)    
  7     {}
  8     BsNode* Find(const K& date){       //查找节点
  9         BsNode* pNode = _root;
 10         while (pNode){
 11             if (pNode->date_ == date){
 12                 return pNode;
 13             }
 14             else if (pNode->date_ > date){
 15                 pNode = pNode->rightC;
 16             }
 17             else
 18                 pNode = pNode->leftC;
 19         }
 20         return nullptr;
 21     }
 22     bool Insert(const K& date){
 23         BsNode *pNode = _root;
 24         BsNode *parent=nullptr;
 25         if (_root == nullptr){      //空树时开辟空间定义为根节点
 26             _root = new BsNode(date);
 27             return true;
 28         }
 29         else if (Find(date)){   //存在相同结点不进行插入
 30             return false;
 31         }
 32         else{
 33             while (pNode){         //找到插入位置,但是这里循环结束后只确认了父母结点,是做左孩子还是右孩子不确认( 因为此时值为nullptr )
 34                 parent = pNode;
 35                 if (pNode->date_ > date){
 36                     pNode = pNode->leftC;
 37                 }
 38                 else{
 39                     pNode = pNode->rightC;
 40                 }
 41             }
 42             pNode = new BsNode(date);    //构造结点
 43             if (parent->date_ > date){       //确认是做左孩子还是右孩子
 44                 parent->leftC = pNode;
 45             }
 46             else{
 47                 parent->rightC = pNode;
 48             }
 49             return true;
 50         }
 51     }
 52 
 53     bool Delete(const K& date){
 54         BsNode *pNode = _root;
 55         BsNode *parent = nullptr;
 56         if (pNode == nullptr){    //空树情况
 57             return false;
 58         }
 59         while (pNode){      //找到要删除的结点
 60             if (pNode->date_ == date){
 61                 break;
 62             }
 63             else if (pNode->date_ < date){
 64                 parent = pNode;
 65                 pNode = pNode->rightC;
 66             }
 67             else{
 68                 parent = pNode;
 69                 pNode = pNode->leftC;
 70             }
 71         }
 72         //BsNode *pdel=pNode;
 73         if (pNode == parent){      //要删除的点是根节点
 74             if (pNode->leftC){
 75                 pNode = pNode->leftC;
 76             }
 77             else if (pNode->rightC){
 78                 pNode = pNode->rightC;
 79             }
 80             else{
 81                 pNode = nullptr;
 82             }
 83         }
 84         if (pNode == nullptr){   // 没有找到要删除的节点
 85             return false;
 86         }
 87         if (pNode->rightC && pNode->leftC == nullptr){  //结点只有右子树
 88             if (pNode == parent->leftC){
 89                 parent->leftC = pNode->rightC;
 90             }
 91             else{
 92                 parent->rightC = pNode->rightC;
 93             }
 94         }
 95         else if (pNode->leftC && pNode->rightC == nullptr){   //结点只有左子树
 96             if (pNode == parent->leftC){
 97                 parent->leftC = pNode->leftC;
 98             }
 99             else{
100                 parent->rightC = pNode->leftC;
101             }
102         }
103         else if (pNode->leftC && pNode->rightC){    //儿女俱全
104             if (pNode == parent->leftC){   //要删除的节点是父母节点的左孩子,删除后的位置要由原先节点的右孩子替代
105                 pNode->rightC->leftC = pNode->leftC;
106                 parent->leftC = pNode->rightC;
107             }
108             else{
109                 pNode->leftC->rightC= pNode->rightC;  //要删除的节点是父母节点的右孩子,删除后的位置要由原先节点的左孩子替代
110                 parent->rightC = pNode->leftC;
111             }
112         }
113         else{                                        //无子可依
114             if (pNode == parent->leftC){
115                 parent->leftC = nullptr;
116             }
117             else{
118                 parent->rightC = nullptr;
119             }
120         }
121         delete pNode;     //在连接完成后最后再进行删除
122         return true;
123     }
124 
125     BsNode* IfLeftMost(){
126         if (_root == nullptr){
127             return nullptr;
128         }
129         BsNode *pNode = _root;
130         while (pNode->leftC){
131             pNode = pNode->leftC;
132         }
133         return pNode;
134     }
135     BsNode* IfRightMost(){
136         if (_root == nullptr){
137             return nullptr;
138         }
139         BsNode *pNode = _root;
140         while (pNode->rightC){
141             pNode = pNode->rightC;
142         }
143         return pNode;
144     }
145     void InOrder(){  //定义一个借口给外部调用,因为根节点在这里是private权限
146         InOrder(_root);
147         cout << endl;
148     }
149 
150 private:
151     void InOrder(BsNode *pNode){    //二叉树的中序遍历,用来检查结果(二叉搜索树中序遍历应该是一个有序序列)
152         if (pNode){
153             InOrder(pNode->leftC);
154             cout << pNode->date_ << ' ';
155             InOrder(pNode->rightC);
156         }
157     }
158 private:
159     BsNode *_root;
160 };

猜你喜欢

转载自www.cnblogs.com/Kaniso-Vok/p/12052423.html