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