首先是概念:
二叉搜索树又称二叉排序树,它具有以下的性质:
- 若是左子树不为空,则左子树上所有节点的值小于根节点的值
- 若是右子树不为空,则右子树上所有结点的值大于根节点的值
- 二叉搜索树的左右子树也是二叉搜索树
- 二叉搜索树的中序排列是一个有序数列
再下来是它的实现
首先是构造节点
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 };