《数据结构与算法分析:C语言描述》复习——第四章“树”——二叉搜索树

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 }
原文地址:https://www.cnblogs.com/zhuli19901106/p/3788982.html