2014.06.14 23:27
简介:
二叉搜索树是学习二叉树之后,接触的第一个实用数据结构。特点是,左子树全部小于根,右子树全部大于根,元素不重复。一般能够支持对数级别的增删改查操作,但在二叉树发生倾斜的情况下,效率会下降至线性。下面给出插入、删除、查找的示意图。修改可以认为是先删除后插入。
图示:
实现:
1 // My implementation for binary search tree. 2 #include <iostream> 3 #include <string> 4 #include <sstream> 5 using namespace std; 6 7 struct TreeNode { 8 int val; 9 TreeNode *left; 10 TreeNode *right; 11 TreeNode(int _val): val(_val), left(nullptr), right(nullptr) {}; 12 }; 13 14 class BinarySearchTree { 15 public: 16 BinarySearchTree() { 17 m_root = nullptr; 18 } 19 20 bool empty() { 21 return m_root == nullptr; 22 } 23 24 void clear() { 25 _deleteTree(m_root); 26 } 27 28 void insertNode(const int &val) { 29 if (m_root == nullptr) { 30 m_root = new TreeNode(val); 31 return; 32 } 33 TreeNode *ptr = _findNode(val); 34 if (val < ptr->val) { 35 ptr->left = new TreeNode(val); 36 } else if (val > ptr->val) { 37 ptr->right = new TreeNode(val); 38 } 39 } 40 41 void deleteNode(const int &val) { 42 if (m_root == nullptr) { 43 return; 44 } 45 46 TreeNode *par, *cur; 47 48 par = nullptr; 49 cur = m_root; 50 while (cur != nullptr) { 51 if (val < cur->val) { 52 par = cur; 53 cur = cur->left; 54 } else if (val > cur->val) { 55 par = cur; 56 cur = cur->right; 57 } else { 58 break; 59 } 60 } 61 62 if (cur == nullptr) { 63 return; 64 } 65 66 if (cur->left != nullptr) { 67 _shiftLeft(cur); 68 return; 69 } 70 71 if (cur->right != nullptr) { 72 _shiftRight(cur); 73 return; 74 } 75 76 if (par == nullptr) { 77 delete cur; 78 m_root = nullptr; 79 } else if (cur == par->left) { 80 delete cur; 81 par->left = nullptr; 82 } else { 83 delete cur; 84 par->right = nullptr; 85 } 86 } 87 88 void updateNode(const int &old_val, const int &new_val) { 89 deleteNode(old_val); 90 insertNode(new_val); 91 } 92 93 bool contains(const int &val) { 94 TreeNode *ptr = _findNode(val); 95 return ptr == nullptr ? false : ptr->val == val ? true : false; 96 } 97 98 string preorderTraversal() { 99 string result; 100 _preorderTraversalRecursive(m_root, result); 101 return result; 102 } 103 104 string inorderTraversal() { 105 string result; 106 _inorderTraversalRecursive(m_root, result); 107 return result; 108 } 109 110 string postorderTraversal() { 111 string result; 112 _postorderTraversalRecursive(m_root, result); 113 return result; 114 } 115 116 ~BinarySearchTree() { 117 clear(); 118 } 119 private: 120 TreeNode *m_root; 121 122 void _deleteTree(TreeNode *&root) { 123 if (root == nullptr) { 124 return; 125 } 126 _deleteTree(root->left); 127 _deleteTree(root->right); 128 delete root; 129 root = nullptr; 130 } 131 132 TreeNode* _findNode(const int &val) { 133 TreeNode *ptr; 134 135 ptr = m_root; 136 while (ptr != nullptr) { 137 if (val < ptr->val) { 138 if (ptr->left != nullptr) { 139 ptr = ptr->left; 140 } else { 141 return ptr; 142 } 143 } else if (val > ptr->val) { 144 if (ptr->right != nullptr) { 145 ptr = ptr->right; 146 } else { 147 return ptr; 148 } 149 } else { 150 return ptr; 151 } 152 } 153 return ptr; 154 } 155 156 void _preorderTraversalRecursive(const TreeNode *root, string &result) { 157 result.push_back('{'); 158 if (root == nullptr) { 159 // '#' represents NULL. 160 result.push_back('#'); 161 } else { 162 result.append(to_string(root->val)); 163 _preorderTraversalRecursive(root->left, result); 164 _preorderTraversalRecursive(root->right, result); 165 } 166 result.push_back('}'); 167 } 168 169 void _inorderTraversalRecursive(const TreeNode *root, string &result) { 170 result.push_back('{'); 171 if (root == nullptr) { 172 // '#' represents NULL. 173 result.push_back('#'); 174 } else { 175 _inorderTraversalRecursive(root->left, result); 176 result.append(to_string(root->val)); 177 _inorderTraversalRecursive(root->right, result); 178 } 179 result.push_back('}'); 180 } 181 182 void _postorderTraversalRecursive(const TreeNode *root, string &result) { 183 result.push_back('{'); 184 if (root == nullptr) { 185 // '#' represents NULL. 186 result.push_back('#'); 187 } else { 188 _postorderTraversalRecursive(root->left, result); 189 _postorderTraversalRecursive(root->right, result); 190 result.append(to_string(root->val)); 191 } 192 result.push_back('}'); 193 } 194 195 void _shiftLeft(TreeNode *root) { 196 TreeNode *cur, *par; 197 198 // root and root->left is guaranteed to be non-empty. 199 par = root; 200 cur = par->left; 201 202 while (cur->right != nullptr) { 203 par = cur; 204 cur = cur->right; 205 } 206 root->val = cur->val; 207 208 if (cur->left != nullptr) { 209 _shiftLeft(cur); 210 return; 211 } 212 213 if (cur->right != nullptr) { 214 _shiftRight(cur); 215 return; 216 } 217 218 if (cur->val < par->val) { 219 delete par->left; 220 par->left = nullptr; 221 } else { 222 delete par->right; 223 par->right = nullptr; 224 } 225 } 226 227 void _shiftRight(TreeNode *root) { 228 TreeNode *cur, *par; 229 230 // root and root->right is guaranteed to be non-empty. 231 par = root; 232 cur = par->right; 233 234 while (cur->left != nullptr) { 235 par = cur; 236 cur = cur->left; 237 } 238 root->val = cur->val; 239 240 if (cur->left != nullptr) { 241 _shiftLeft(cur); 242 return; 243 } 244 245 if (cur->right != nullptr) { 246 _shiftRight(cur); 247 return; 248 } 249 250 if (cur->val < par->val) { 251 delete par->left; 252 par->left = nullptr; 253 } else { 254 delete par->right; 255 par->right = nullptr; 256 } 257 } 258 }; 259 260 int main() 261 { 262 BinarySearchTree bst; 263 264 bst.insertNode(5); 265 bst.insertNode(3); 266 bst.insertNode(14); 267 bst.insertNode(2); 268 bst.insertNode(4); 269 bst.insertNode(9); 270 bst.insertNode(15); 271 bst.insertNode(7); 272 bst.insertNode(8); 273 cout << bst.preorderTraversal() << endl; 274 bst.deleteNode(14); 275 cout << bst.preorderTraversal() << endl; 276 bst.deleteNode(5); 277 cout << bst.preorderTraversal() << endl; 278 279 bst.clear(); 280 bst.insertNode(1); 281 cout << bst.preorderTraversal() << endl; 282 bst.deleteNode(1); 283 cout << bst.preorderTraversal() << endl; 284 285 return 0; 286 }