二叉搜索树是一种特殊的二叉树,查找、插入时间复杂度较低O(log n),它有这几个性质:
- 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值
- 若任意节点的右子树不空,则右子树上所有节点的值均大于或等于它的根节点的值
- 任意节点的左、右子树也分别为二叉搜索树
- 空树也是二叉搜索树
查找:
由于它的这些性质,所以在查找的时候从根节点开始查找
在二叉搜索树b中查找x的过程为:
若b是空树,则搜索失败
若x等于b节点数据域的值,则查找成功
若x小于b节点数据域的值,则搜索左子树
若x大于b节点数据域的值,则搜索右子树
由于搜索的长度为树的高度,所以在一个平衡的情况下搜索效率为O(log n)
插入:
向一个二叉搜索树b中插入一个节点s的算法,过程为:
若树是空树,则将s所指节点作为根节点插入
若s->data等于b的根节点的数据域之值,则返回
若s->data小于b的根节点的数据域之值,则把s所指节点插入到左子树中
若s->data大于b的根节点的数据域之值,则把s所指节点插入到右子树中
同样插入效率为O(log n)
删除:
- 若要删除的结点无孩子结点,直接删除即可
- 若要删除的结点只有左孩子结点,使被删除节点的双亲结点指向被删除节点的左孩子结点
- 若要删除的结点只有右孩子结点,使被删除节点的双亲结点指向被删除结点的右孩子结点
- 若要删除的结点有左、右孩子结点,在它的右子树中寻找关键码最小或在左子树寻找关键码最大的节点,用它的值填补到被删除节点中,效率O(log n)
但这这样存在一些问题,当二叉搜索树退化为左右单支时,它的平均比较次数为n/2,这样二叉搜索树性能就失去了,所以我们可以通过别的办法来改进,如AVL树、红黑树…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
#include <iostream>
template <class T> struct BSTNode { BSTNode(const T& data = T()) : _left(nullptr) , _right(nullptr) , _data(data) {}
BSTNode<T>* _left; BSTNode<T>* _right; T _data; };
template <class T> class BSTree { public: typedef BSTNode<T> Node; typedef Node* pNode;
BSTree() : _root(nullptr) {}
BSTree(const BSTree<T>& bst) { _root = Copy(bst._root); }
BSTree<T>& operator=(const BSTree<T>& bst) { if (this != &bst) { if (_root) { destroy(_root); } _root = Copy(bst._root); } return *this; }
~BSTree() { destroy(_root); }
pNode Find(const T& data) { if (_root == nullptr) { return nullptr; } pNode cur = _root; while (cur) { if (cur->_data == data) { return cur; } else if (cur->_data > data) { cur = cur->_left; } else { cur = cur->_right; } } return nullptr; }
bool Insert(const T& data) { if (_root == nullptr) { _root = new Node(data); return true; } pNode cur = _root; pNode parent = nullptr; while (cur) { parent = cur; if (cur->_data == data) { return false; } else if (cur->_data > data) { cur = cur->_left; } else { cur = cur->_right; } } cur = new Node(data); if (parent->_data > data) { parent->_left = cur; } else { parent->_right = cur; } return true; }
bool Erase(const T& data) { if (_root == nullptr) { return false; } pNode cur = _root; pNode parent = nullptr; while (cur) { if (cur->_data == data) { if (cur->_right == nullptr) { if (cur != _root) { if (parent->_left == cur) { parent->_left = cur->_left; } else { parent->_right = cur->_left; } } else { _root = cur->_left; } delete cur; cur = nullptr; } else if (cur->_left == nullptr) { if (cur != _root) { if (parent->_left == cur) { parent->_left = cur->_right; } else { parent->_right = cur->_right; } } else { _root = cur->_right; } delete cur; cur = nullptr; } else { pNode leftMax = cur->_left; parent = cur; while (leftMax->_right) { parent = leftMax; leftMax = leftMax->_right; } cur->_data = leftMax->_data; if (parent->_left == leftMax) { parent->_left = leftMax->_left; } else { parent->_right = leftMax->_left; } delete leftMax; leftMax = nullptr; } return true; } parent = cur; if (cur->_data > data) { cur = cur->_left; } else { cur = cur->_right; } } return false; }
void Inorder() { _Inorder(_root); std::cout << std::endl; } private: pNode Copy(pNode root) { if (root == nullptr) { return root; } pNode newRoot = new Node(root->_data); newRoot->_left = Copy(root->_left); newRoot->_right = Copy(root->_right); return newRoot; }
void destroy(pNode root) { if (root != nullptr) { destroy(root->_left); destroy(root->_right); delete root; root = nullptr; } }
void _Inorder(pNode root) { if (root != nullptr) { _Inorder(root->_left); std::cout << root->_data << " "; _Inorder(root->_right); } }
pNode _root; };
|