第五十八课 树形结构的层次遍历

Posted wanmeishenghuo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第五十八课 树形结构的层次遍历相关的知识,希望对你有一定的参考价值。

技术分享图片

通用树结构是一种容器,里面装有数据元素,我们有遍历元素的需求。

技术分享图片

 

 非线性决定了树中的每个结点没有固定的编号方式。

技术分享图片

 

技术分享图片

 

技术分享图片

 

将队列中队首的指针定义成遍历时的游标,根节点进入队列后,游标指向根节点。

队头元素弹出,队首的指针就指向了别的元素,这就相当于移动了游标。

技术分享图片

 

添加遍历相关的程序:

  1 #ifndef GTREE_H
  2 #define GTREE_H
  3 
  4 #include "Tree.h"
  5 #include "GTreeNode.h"
  6 #include "Exception.h"
  7 #include "LinkQueue.h"
  8 
  9 namespace DTLib
 10 {
 11 
 12 template < typename T >
 13 class GTree : public Tree<T>
 14 {
 15 protected:
 16     LinkQueue<GTreeNode<T>*> m_queue;
 17 
 18     GTree(const GTree<T>&);
 19     GTree<T>& operator = (const GTree<T>&);
 20 
 21     GTreeNode<T>* find(GTreeNode<T>* node, const T& value) const
 22     {
 23         GTreeNode<T>* ret = NULL;
 24 
 25         if( node != NULL )
 26         {
 27             if( node->value == value )
 28             {
 29                 return node;
 30             }
 31             else
 32             {
 33                 for(node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
 34                 {
 35                     ret = find(node->child.current(), value);
 36                 }
 37             }
 38         }
 39 
 40         return ret;
 41     }
 42 
 43     GTreeNode<T>* find(GTreeNode<T>* node,  GTreeNode<T>* obj) const
 44     {
 45         GTreeNode<T>* ret = NULL;
 46 
 47         if( node == obj )
 48         {
 49             return node;
 50         }
 51         else
 52         {
 53             if( node != NULL )
 54             {
 55                 for( node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
 56                 {
 57                     ret = find(node->child.current(), obj);
 58                 }
 59             }
 60         }
 61 
 62         return ret;
 63     }
 64 
 65     void free(GTreeNode<T>* node)
 66     {
 67         if( node != NULL )
 68         {
 69             for(node->child.move(0); !node->child.end(); node->child.next())
 70             {
 71                 free(node->child.current());
 72             }
 73 
 74             if( node->flag() )
 75             {
 76                 delete node;
 77             }
 78         }
 79     }
 80 
 81     void remove(GTreeNode<T>* node, GTree<T>*& ret)
 82     {
 83         ret = new GTree<T>();
 84 
 85         if( ret == NULL )
 86         {
 87             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create tree...");
 88         }
 89         else
 90         {
 91             if( root() == node )
 92             {
 93                 this->m_root = NULL;
 94             }
 95             else
 96             {
 97                 LinkList<GTreeNode<T>*>& child = dynamic_cast<GTreeNode<T>*>(node->parent)->child;
 98 
 99                 child.remove(child.find(node));
100 
101                 node->parent = NULL;
102             }
103 
104             ret->m_root = node;
105         }
106     }
107 
108     int count(GTreeNode<T>* node) const
109     {
110         int ret = 0;
111 
112         if( node != NULL )
113         {
114             ret = 1;
115 
116             //node如果没有孩子,则for不执行
117             for(node->child.move(0); !node->child.end(); node->child.next())
118             {
119                 ret += count(node->child.current());
120             }
121         }
122 
123         return ret;
124     }
125 
126     int height(GTreeNode<T>* node) const
127     {
128         int ret = 0;
129 
130         if( node != NULL )
131         {
132             for(node->child.move(0); !node->child.end(); node->child.next())
133             {
134                 int h = height(node->child.current());
135 
136                 if( ret < h )
137                 {
138                     ret = h;
139                 }
140             }
141 
142             ret = ret + 1;
143         }
144 
145         return ret;
146     }
147 
148     int degree(GTreeNode<T>* node) const
149     {
150         int ret = 0;
151 
152         if( node != NULL )
153         {
154             ret = node->child.length();  //根节点的度数
155 
156             for(node->child.move(0); !node->child.end(); node->child.next())
157             {
158                 int d = degree(node->child.current());
159 
160                 if( ret < d )
161                 {
162                     ret = d;
163                 }
164             }
165         }
166 
167         return ret;
168     }
169 public:
170     GTree()
171     {
172 
173     }
174     bool insert(TreeNode<T>* node)
175     {
176         bool ret = true;
177 
178         if( node != NULL )
179         {
180             if( this->m_root == NULL ) //如果待插入节点的父节点为空,则这个节点将为根节点
181             {
182                 node->parent = NULL;
183                 this->m_root = node;
184             }
185             else
186             {
187                 GTreeNode<T>* np = find(node->parent);
188 
189                 if( np != NULL )
190                 {
191                     GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);
192 
193                     if( np->child.find(n) < 0 )
194                     {
195                         np->child.insert(n);
196                     }
197                 }
198                 else
199                 {
200                     THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node...");
201                 }
202             }
203         }
204         else
205         {
206             THROW_EXCEPTION(InvalidParameterException, "Parameter node cannot be NULL ...");
207         }
208 
209         return ret;
210     }
211 
212     bool insert(const T& value, TreeNode<T>* parent)
213     {
214         bool ret = true;
215 
216         GTreeNode<T>* node = GTreeNode<T>::NewNode();
217 
218         if( node != NULL )
219         {
220             node->value = value;
221             node->parent = parent;
222 
223             insert(node);
224         }
225         else
226         {
227             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ...");
228         }
229 
230         return ret;
231     }
232 
233     //删除的节点的子节点我们还需要处理,因此要返回删除节点的指针,这样有机会对里面的元素做进一步操作
234     SharedPointer< Tree<T> > remove(const T& value)
235     {
236         GTree<T>* ret = NULL;
237 
238         GTreeNode<T>* node = find(value);
239 
240         if( node == NULL )
241         {
242             THROW_EXCEPTION(InvalidParameterException, "can not find the node ...");
243         }
244         else
245         {
246             remove(node, ret);
247 
248             m_queue.clear();
249         }
250 
251         return ret;
252     }
253 
254     SharedPointer< Tree<T> > remove(TreeNode<T>* node)
255     {
256         GTree<T>* ret = NULL;
257 
258         node = find(node);
259 
260         if( node == NULL )
261         {
262             THROW_EXCEPTION(InvalidParameterException, "parameter node is invalid ...");
263         }
264         else
265         {
266             remove(dynamic_cast<GTreeNode<T>*>(node), ret);
267 
268             m_queue.clear();
269         }
270 
271         return ret;
272     }
273 
274     GTreeNode<T>* find(const T& value) const  // 返回GTreeNode,赋值兼容性
275     {
276         return find(root(), value);
277     }
278 
279     GTreeNode<T>* find(TreeNode<T>* node) const
280     {
281         return find(root(), dynamic_cast<GTreeNode<T>*>(node));
282     }
283 
284     GTreeNode<T>* root() const
285     {
286         return dynamic_cast<GTreeNode<T>*>(this->m_root);
287     }
288 
289     int degree() const
290     {
291         return degree(root());
292     }
293     int count() const
294     {
295         return count(root());
296     }
297 
298     int height() const
299     {
300         return height(root());
301     }
302 
303     void clear()
304     {
305         free(root());
306 
307         this->m_root = NULL;
308 
309         m_queue.clear();
310     }
311 
312     bool begin()
313     {
314         bool ret = ( root() != NULL );
315 
316         if( ret )
317         {
318             m_queue.clear();
319             m_queue.add(root());
320         }
321 
322         return ret;
323     }
324 
325     bool end()
326     {
327         return (m_queue.length() == 0);
328     }
329 
330     bool next()
331     {
332         bool ret = (m_queue.length() > 0);
333 
334         if( ret )
335         {
336             GTreeNode<T>* node = m_queue.front();
337 
338             m_queue.remove();  //将对头元素出队,相当于移动游标
339 
340             for(node->child.move(0); !node->child.end(); node->child.next())
341             {
342                 m_queue.add(node->child.current());
343             }
344         }
345 
346         return ret;
347     }
348 
349     T current()
350     {
351         if( !end() )  //遍历的过程当中调用current函数才有意义
352         {
353             return m_queue.front()->value;
354         }
355         else
356         {
357             THROW_EXCEPTION(InvalidOperationException, "No value at current position...");
358         }
359     }
360 
361     ~GTree()
362     {
363         clear();
364     }
365 };
366 
367 }
368 
369 #endif // GTREE_H

测试程序如下:

 1 #include <iostream>
 2 #include "GTree.h"
 3 #include "GTreeNode.h"
 4 
 5 
 6 using namespace std;
 7 using namespace DTLib;
 8 
 9 
10 int main()
11 {
12     GTree<char> t;
13     GTreeNode<char>* node = NULL;
14     GTreeNode<char> root;
15 
16     root.value = A;
17     root.parent = NULL;
18 
19     t.insert(&root);
20 
21     node = t.find(A);
22     t.insert(B, node);
23     t.insert(C, node);
24     t.insert(D, node);
25 
26     node = t.find(B);
27     t.insert(E, node);
28     t.insert(F, node);
29 
30     node = t.find(E);
31     t.insert(K, node);
32     t.insert(L, node);
33 
34     node = t.find(C);
35     t.insert(G, node);
36 
37     node = t.find(D);
38     t.insert(H, node);
39     t.insert(I, node);
40     t.insert(J, node);
41 
42     node = t.find(H);
43     t.insert(M, node);
44 
45     cout << t.degree() << endl;
46 
47     for(t.begin(); !t.end(); t.next())
48     {
49         cout << t.current() << endl;
50     }
51 
52     return 0;
53 }

结果如下:

技术分享图片

 

 

 

小结:

技术分享图片

 

以上是关于第五十八课 树形结构的层次遍历的主要内容,如果未能解决你的问题,请参考以下文章

第五十八课自定义模型类(上)------------------狄泰软件学院

第五十八题(从尾到头输出链表)

python五十八课——正则表达式(分组)

python五十八课——正则表达式(切割)

python五十八课——正则表达式(替换)

第五十八节,上下文管理