《数据结构与算法分析C++描述》 搜索二叉树的C++实现
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
《数据结构与算法分析c++描述》 Mark Allen Weiss著 人民邮电大学出版 中文版第93-100面,搜索二叉树
需要说明一点的是,此搜索二叉树并没有平衡算法,所以可能会导致有可能出现O(M logN)的最坏情况。
并且几乎所有代码都用递归实现,所以效率并不是太高,并且当N足够大的时候,很多操作都可能导致栈溢出。但是因为对于树的操作用递归描述起来理解上还是比循环好的多,并且以后可以用平衡算法,所以这里都用递归了。
搜索二叉树的实现:
1
2 #ifndef __BINARY_SEARCH_TREE_H__
3 #define __BINARY_SEARCH_TREE_H__
4
5 templatetypenameT>
6 classCBinarySearchTree
7 {
8 public:
9 CBinarySearchTree():mpRoot(NULL) { }
10 CBinarySearchTree(constCBinarySearchTree& aOrig)
11 {
12 mpRoot = Clone(aOrig.mpRoot);
13 }
14 ~CBinarySearchTree()
15 {
16 MakeEmpty();
17 }
18
19
20 // const member function
21
22 constT* FindMin() const;
23 constT* FindMax() const;
24
25 boolContains( constT& aElement) const;
26 boolIsEmpty() const
27 {
28 return(mpRoot != NULL) ? true: false;
29 }
30
31 // I don't know how to print it in a good format
32 //void PrintTree() const;
33
34
35 // non-const member function
36
37 voidMakeEmpty();
38 voidInsert( constT& aElement);
39 voidRemove( constT& aElement);
40
41 constCBinarySearchTree& operator=(constCBinarySearchTree& aOrig);
42
43 private:
44 structCBinaryNode
45 {
46 CBinaryNode(constT& aElement, CBinaryNode* apLeft, CBinaryNode* apRight)
47 : mElement(aElement),mpLeft(apLeft),mpRight(apRight) {}
48
49 T mElement;
50 CBinaryNode *mpLeft;
51 CBinaryNode *mpRight;
52 };
53
54 // Root Node
55 CBinaryNode *mpRoot;
56
57
58 // private member function to call recursively
59
60
61 // I don't like to use reference to pointer
62 // so I used pointer to pointer instead
63 voidInsert(constT& aElement, CBinaryNode** appNode) const;
64 voidRemove(constT& aElement, CBinaryNode** appNode) const;
65
66 CBinaryNode* FindMin(CBinaryNode* apNode) const;
67 CBinaryNode* FindMax(CBinaryNode* apNode) const;
68 boolContains(constT& aElement, CBinaryNode * apNode) const;
69 voidMakeEmpty(CBinaryNode** apNode);
70 //void PrintTree(CBinaryNode* apNode) const;
71 CBinaryNode* Clone(CBinaryNode* apNode) const;
72
73 };
74
75
76 templatetypenameT>
77 boolCBinarySearchTree<t>::Contains(<span style="color:seagreen"><strong>const</strong></span>T& aElement) <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">78 </span>{<br><span style="color:#804040">79 </span><span style="color:#804040"><strong>return</strong></span>Contains(aElement, mpRoot);<br><span style="color:#804040">80 </span>}<br><span style="color:#804040">81 </span><br><span style="color:#804040">82 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">83 </span><span style="color:seagreen"><strong>bool</strong></span>CBinarySearchTree<t>::Contains(<span style="color:seagreen"><strong>const</strong></span>T &aElement, CBinaryNode *apNode) <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">84 </span>{<br><span style="color:#804040">85 </span><span style="color:#804040"><strong>if</strong></span>( <span style="color:fuchsia">NULL</span>== apNode )<br><span style="color:#804040">86 </span>{<br><span style="color:#804040">87 </span><span style="color:#804040"><strong>return</strong></span><span style="color:fuchsia">false</span>;<br><span style="color:#804040">88 </span>}<br><span style="color:#804040">89 </span><span style="color:#804040"><strong>else</strong></span><span style="color:#804040"><strong>if</strong></span>( aElement mElement )<br><span style="color:#804040">90 </span>{<br><span style="color:#804040">91 </span><span style="color:#804040"><strong>return</strong></span>Contains(aElement, apNode->mpLeft);<br><span style="color:#804040">92 </span>}<br><span style="color:#804040">93 </span><span style="color:#804040"><strong>else</strong></span><span style="color:#804040"><strong>if</strong></span>( aElement > apNode->mElement )<br><span style="color:#804040">94 </span>{<br><span style="color:#804040">95 </span><span style="color:#804040"><strong>return</strong></span>Contains(aElement, apNode->mpRight);<br><span style="color:#804040">96 </span>}<br><span style="color:#804040">97 </span><span style="color:#804040"><strong>else</strong></span><br><span style="color:#804040">98 </span>{<br><span style="color:#804040">99 </span><span style="color:#804040"><strong>return</strong></span><span style="color:fuchsia">true</span>;<span style="color:blue">// Find it</span><br><span style="color:#804040">100 </span>}<br><span style="color:#804040">101 </span>}<br><span style="color:#804040">102 </span><br><span style="color:#804040">103 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">104 </span><span style="color:seagreen"><strong>void</strong></span>CBinarySearchTree<t>::Insert(<span style="color:seagreen"><strong>const</strong></span>T &aElement)<br><span style="color:#804040">105 </span>{<br><span style="color:#804040">106 </span>Insert(aElement, &mpRoot);<br><span style="color:#804040">107 </span>}<br><span style="color:#804040">108 </span><br><span style="color:#804040">109 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">110 </span><span style="color:seagreen"><strong>void</strong></span>CBinarySearchTree<t>::Insert(<span style="color:seagreen"><strong>const</strong></span>T& aElement, CBinaryNode** appNode) <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">111 </span>{<br><span style="color:#804040">112 </span>CBinaryNode *lpNode = *appNode;<br><span style="color:#804040">113 </span><span style="color:#804040"><strong>if</strong></span>(<span style="color:fuchsia">NULL</span>== lpNode)<br><span style="color:#804040">114 </span>{<br><span style="color:#804040">115 </span>*appNode = <span style="color:#804040"><strong>new</strong></span>CBinaryNode(aElement, <span style="color:fuchsia">NULL</span>, <span style="color:fuchsia">NULL</span>);<br><span style="color:#804040">116 </span>}<br><span style="color:#804040">117 </span><span style="color:#804040"><strong>else</strong></span><span style="color:#804040"><strong>if</strong></span>( aElement mElement )<br><span style="color:#804040">118 </span>{<br><span style="color:#804040">119 </span>Insert(aElement, &(lpNode->mpLeft) );<br><span style="color:#804040">120 </span>}<br><span style="color:#804040">121 </span><span style="color:#804040"><strong>else</strong></span><span style="color:#804040"><strong>if</strong></span>( aElement > lpNode->mElement)<br><span style="color:#804040">122 </span>{<br><span style="color:#804040">123 </span>Insert(aElement, &(lpNode->mpRight) );<br><span style="color:#804040">124 </span>}<br><span style="color:#804040">125 </span><br><span style="color:#804040">126 </span><span style="color:blue">// had not deal with duplicate</span><br><span style="color:#804040">127 </span>}<br><span style="color:#804040">128 </span><br><span style="color:#804040">129 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">130 </span><span style="color:seagreen"><strong>void</strong></span>CBinarySearchTree<t>::Remove(<span style="color:seagreen"><strong>const</strong></span>T &aElement)<br><span style="color:#804040">131 </span>{<br><span style="color:#804040">132 </span>Remove(aElement, &mpRoot);<br><span style="color:#804040">133 </span>}<br><span style="color:#804040">134 </span><br><span style="color:#804040">135 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">136 </span><span style="color:seagreen"><strong>void</strong></span>CBinarySearchTree<t>::Remove(<span style="color:seagreen"><strong>const</strong></span>T &aElement, CBinaryNode** appNode) <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">137 </span>{<br><span style="color:#804040">138 </span>CBinaryNode* lpNode = *appNode;<br><span style="color:#804040">139 </span><span style="color:#804040"><strong>if</strong></span>(<span style="color:fuchsia">NULL</span>== lpNode)<br><span style="color:#804040">140 </span>{<br><span style="color:#804040">141 </span><span style="color:#804040"><strong>return</strong></span>; <span style="color:blue">// Item removing is not exist</span><br><span style="color:#804040">142 </span>}<br><span style="color:#804040">143 </span><br><span style="color:#804040">144 </span><span style="color:#804040"><strong>if</strong></span>( aElement mElement )<br><span style="color:#804040">145 </span>{<br><span style="color:#804040">146 </span>Remove(aElement, &(lpNode->mpLeft) );<br><span style="color:#804040">147 </span>}<br><span style="color:#804040">148 </span><span style="color:#804040"><strong>else</strong></span><span style="color:#804040"><strong>if</strong></span>( aElement > lpNode->mElement )<br><span style="color:#804040">149 </span>{<br><span style="color:#804040">150 </span>Remove(aElement, &(lpNode->mpRight) );<br><span style="color:#804040">151 </span>}<br><span style="color:#804040">152 </span><span style="color:#804040"><strong>else</strong></span><span style="color:#804040"><strong>if</strong></span>( <span style="color:fuchsia">NULL</span>!= lpNode->mpLeft && <span style="color:fuchsia">NULL</span>!= lpNode->mpRight) <span style="color:blue">// Two children</span><br><span style="color:#804040">153 </span>{<br><span style="color:#804040">154 </span>lpNode->mElement = FindMin(lpNode->mpRight)->mElement;<br><span style="color:#804040">155 </span>Remove( lpNode->mElement, &(lpNode->mpRight) );<br><span style="color:#804040">156 </span>}<br><span style="color:#804040">157 </span><span style="color:#804040"><strong>else</strong></span><br><span style="color:#804040">158 </span>{<br><span style="color:#804040">159 </span>CBinaryNode *lpOldNode = lpNode;<br><span style="color:#804040">160 </span><span style="color:blue">// Even if lpNode equal NULL, this is still the right behavior we need</span><br><span style="color:#804040">161 </span><span style="color:blue">// Yeah,When lpNode have no children,we make lpNode equal NULL</span><br><span style="color:#804040">162 </span>*appNode = (lpNode->mpLeft != <span style="color:fuchsia">NULL</span>) ? lpNode->mpLeft : lpNode->mpRight;<br><span style="color:#804040">163 </span><span style="color:#804040"><strong>delete</strong></span>lpOldNode;<br><span style="color:#804040">164 </span>}<br><span style="color:#804040">165 </span>}<br><span style="color:#804040">166 </span><br><span style="color:#804040">167 </span><br><span style="color:#804040">168 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">169 </span><span style="color:seagreen"><strong>const</strong></span>T* CBinarySearchTree<t>::FindMin() <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">170 </span>{<br><span style="color:#804040">171 </span>CBinaryNode* lpNode = FindMin(mpRoot);<br><span style="color:#804040">172 </span><span style="color:#804040"><strong>return</strong></span>(lpNode != <span style="color:fuchsia">NULL</span>) ? &(lpNode->mElement) : <span style="color:fuchsia">NULL</span>;<br><span style="color:#804040">173 </span>}<br><span style="color:#804040">174 </span><br><span style="color:#804040">175 </span><br><span style="color:#804040">176 </span><span style="color:blue">// damn it! So redundant words to fit to C++ syntax</span><br><span style="color:#804040">177 </span><span style="color:blue">// the only way to fix this problom is compositing defines and declares</span><br><span style="color:#804040">178 </span><span style="color:blue">// I even doubt that are there programmers could write it right </span><br><span style="color:#804040">179 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">180 </span><span style="color:seagreen"><strong>typename</strong></span>CBinarySearchTree<t>::CBinaryNode * CBinarySearchTree<t>::FindMin(CBinaryNode* apNode) <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">181 </span>{<br><span style="color:#804040">182 </span><span style="color:#804040"><strong>if</strong></span>( <span style="color:fuchsia">NULL</span>== apNode)<br><span style="color:#804040">183 </span>{<br><span style="color:#804040">184 </span><span style="color:#804040"><strong>return</strong></span><span style="color:fuchsia">NULL</span>;<br><span style="color:#804040">185 </span>}<br><span style="color:#804040">186 </span><span style="color:#804040"><strong>else</strong></span><span style="color:#804040"><strong>if</strong></span>( <span style="color:fuchsia">NULL</span>== apNode->mpLeft)<br><span style="color:#804040">187 </span>{<br><span style="color:#804040">188 </span><span style="color:blue">// Find it</span><br><span style="color:#804040">189 </span><span style="color:#804040"><strong>return</strong></span>apNode;<br><span style="color:#804040">190 </span>}<br><span style="color:#804040">191 </span><span style="color:#804040"><strong>else</strong></span><br><span style="color:#804040">192 </span>{<br><span style="color:#804040">193 </span><span style="color:#804040"><strong>return</strong></span>FindMin(apNode->mpLeft);<br><span style="color:#804040">194 </span>}<br><span style="color:#804040">195 </span>}<br><span style="color:#804040">196 </span><br><span style="color:#804040">197 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">198 </span><span style="color:seagreen"><strong>const</strong></span>T* CBinarySearchTree<t>::FindMax() <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">199 </span>{<br><span style="color:#804040">200 </span>CBinaryNode* lpNode = FindMax(mpRoot);<br><span style="color:#804040">201 </span><span style="color:#804040"><strong>return</strong></span>(lpNode != <span style="color:fuchsia">NULL</span>) ? &(lpNode->mElement) : <span style="color:fuchsia">NULL</span>;<br><span style="color:#804040">202 </span>}<br><span style="color:#804040">203 </span><br><span style="color:#804040">204 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">205 </span><span style="color:seagreen"><strong>typename</strong></span>CBinarySearchTree<t>::CBinaryNode * CBinarySearchTree<t>::FindMax(CBinaryNode* apNode) <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">206 </span>{<br><span style="color:#804040">207 </span><span style="color:#804040"><strong>if</strong></span>( <span style="color:fuchsia">NULL</span>== apNode)<br><span style="color:#804040">208 </span>{<br><span style="color:#804040">209 </span><span style="color:#804040"><strong>return</strong></span><span style="color:fuchsia">NULL</span>;<br><span style="color:#804040">210 </span>}<br><span style="color:#804040">211 </span><span style="color:#804040"><strong>else</strong></span><span style="color:#804040"><strong>if</strong></span>( <span style="color:fuchsia">NULL</span>== apNode->mpRight)<br><span style="color:#804040">212 </span>{<br><span style="color:#804040">213 </span><span style="color:blue">// Find it</span><br><span style="color:#804040">214 </span><span style="color:#804040"><strong>return</strong></span>apNode;<br><span style="color:#804040">215 </span>}<br><span style="color:#804040">216 </span><span style="color:#804040"><strong>else</strong></span><br><span style="color:#804040">217 </span>{<br><span style="color:#804040">218 </span><span style="color:#804040"><strong>return</strong></span>FindMax(apNode->mpRight);<br><span style="color:#804040">219 </span>}<br><span style="color:#804040">220 </span>}<br><span style="color:#804040">221 </span><br><span style="color:#804040">222 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">223 </span><span style="color:seagreen"><strong>void</strong></span>CBinarySearchTree<t>::MakeEmpty()<br><span style="color:#804040">224 </span>{<br><span style="color:#804040">225 </span>MakeEmpty(&mpRoot);<br><span style="color:#804040">226 </span>}<br><span style="color:#804040">227 </span><br><span style="color:#804040">228 </span><br><span style="color:#804040">229 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">230 </span><span style="color:seagreen"><strong>void</strong></span>CBinarySearchTree<t>::MakeEmpty(CBinaryNode** appNode)<br><span style="color:#804040">231 </span>{<br><span style="color:#804040">232 </span>CBinaryNode* lpNode = *appNode;<br><span style="color:#804040">233 </span><span style="color:#804040"><strong>if</strong></span>( lpNode != <span style="color:fuchsia">NULL</span>)<br><span style="color:#804040">234 </span>{<br><span style="color:#804040">235 </span>MakeEmpty( &(lpNode->mpLeft) );<br><span style="color:#804040">236 </span>MakeEmpty( &(lpNode->mpRight) );<br><span style="color:#804040">237 </span><span style="color:#804040"><strong>delete</strong></span>lpNode;<br><span style="color:#804040">238 </span>}<br><span style="color:#804040">239 </span><br><span style="color:#804040">240 </span>*appNode = <span style="color:fuchsia">NULL</span>;<br><span style="color:#804040">241 </span>}<br><span style="color:#804040">242 </span><br><span style="color:#804040">243 </span><span style="color:blue">// how long the syntax is...............</span><br><span style="color:#804040">244 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">245 </span><span style="color:seagreen"><strong>const</strong></span>CBinarySearchTree<t>& CBinarySearchTree<t>::<span style="color:#804040"><strong>operator</strong></span>=(<span style="color:seagreen"><strong>const</strong></span>CBinarySearchTree<t> &aOrig)<br><span style="color:#804040">246 </span>{<br><span style="color:#804040">247 </span><span style="color:#804040"><strong>if</strong></span>(&aOrig == <span style="color:#804040"><strong>this</strong></span>)<br><span style="color:#804040">248 </span>{<br><span style="color:#804040">249 </span><span style="color:#804040"><strong>return</strong></span>*<span style="color:#804040"><strong>this</strong></span>;<br><span style="color:#804040">250 </span>}<br><span style="color:#804040">251 </span><br><span style="color:#804040">252 </span>MakeEmpty();<br><span style="color:#804040">253 </span>mpRoot = Clone(aOrig.mpRoot);<br><span style="color:#804040">254 </span><br><span style="color:#804040">255 </span><span style="color:#804040"><strong>return</strong></span>*<span style="color:#804040"><strong>this</strong></span>;<br><span style="color:#804040">256 </span><br><span style="color:#804040">257 </span>}<br><span style="color:#804040">258 </span><br><span style="color:#804040">259 </span><span style="color:blue">// when you use nest class and template both,you will find out how long the C++ syntax is.....</span><br><span style="color:#804040">260 </span><span style="color:blue">// I use it once,I ask why couldn't we have a short once again.</span><br><span style="color:#804040">261 </span><span style="color:seagreen"><strong>template</strong></span><strong>typename</strong>T><br><span style="color:#804040">262 </span><span style="color:seagreen"><strong>typename</strong></span>CBinarySearchTree<t>::CBinaryNode* CBinarySearchTree<t>::Clone(CBinaryNode *apNode) <span style="color:seagreen"><strong>const</strong></span><br><span style="color:#804040">263 </span>{<br><span style="color:#804040">264 </span><span style="color:#804040"><strong>if</strong></span>(<span style="color:fuchsia">NULL</span>== apNode)<br><span style="color:#804040">265 </span>{<br><span style="color:#804040">266 </span><span style="color:#804040"><strong>return</strong></span><span style="color:fuchsia">NULL</span>;<br><span style="color:#804040">267 </span>}<br><span style="color:#804040">268 </span><br><span style="color:#804040">269 </span><span style="color:blue">// abuse recursion</span><br><span style="color:#804040">270 </span><span style="color:#804040"><strong>return</strong></span><span style="color:#804040"><strong>new</strong></span>CBinaryNode(apNode->mElement, Clone(apNode->mpLeft), Clone(apNode->mpRight));<br><span style="color:#804040">271 </span>}<br><span style="color:#804040">272 </span><br><span style="color:#804040">273 </span><br><span style="color:#804040">274 </span><br><span style="color:#804040">275 </span><br><span style="color:#804040">276 </span><span style="color:#a020f0">#endif</span><span style="color:blue">// __BINARY_SEARCH_TREE_H__ </span></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t>
测试代码:
1 #include <iostream></iostream>
2 #include "BinarySearchTree.h"
3 usingnamespacestd;
4
5 int_tmain(intargc, _TCHAR* argv[])
6 {
7 CBinarySearchTreeint> loTree;
8
9 loTree.Insert(10);
10 loTree.Insert(20);
11 loTree.Insert(30);
12 loTree.Insert(40);
13 cout "Min: "" Max: "" IsContains(20)"20) 14 loTree.Remove(40);
15 cout "Min: "" Max: "" IsContains(20)"20) 16 loTree.Remove(30);
17 loTree.Remove(20);
18 loTree.Remove(10);
19
20
21 loTree.Insert(40);
22 cout "Min: "" Max: "" IsContains(20)"20) 23 loTree.Insert(30);
24 loTree.Insert(20);
25 loTree.Insert(10);
26 cout "Min: "" Max: "" IsContains(20)"20) 27 loTree.Remove(40);
28 loTree.Remove(30);
29 loTree.Remove(20);
30 loTree.Remove(10);
31
32 loTree.Insert(30);
33 loTree.Insert(40);
34 cout "Min: "" Max: "" IsContains(20)"20) 35 loTree.Insert(10);
36 loTree.Insert(20);
37 cout "Min: "" Max: "" IsContains(20)"20) 38 CBinarySearchTreeint> loTree2 = loTree;
39 cout "Min: "" Max: "" IsContains(20)"20) 40
41 loTree.MakeEmpty();
42
43
44
45 system("pause");
46 return0;
47 }
48
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie