1,为何及如何按层次遍历通用树中的每一个数据元素?
1,通用树结构是一种容器类型的树结构,其用来装数据元素,所以应该提供一种方法来遍历树中的每一个数据结构;
2,往下分析;
2,当前的事实:
1,树是非线性的数据结构,树的结点没有固定的编号方式;
1,也就不能像链表一样统一编号来访问;
3,新的需求:
1,为通用树结构提供新的方法,快速遍历每一个结点;
4,设计思路(游标):
1,在树中定义一个游标(GTreeNode<T>*);
2,遍历开始前将游标指向根结点(root());
3,获取游标指向的数据元素;
4,通过结点中的 child 成员移动游标;
5,提供一组遍历相关的函数,按层次访问树中的数据元素;
5,层次便利算法:
1,原料:class LinkQueue<T>;
2,游标:LinkQueue<T>::front();
3,思想:
1,begin() ==> 将根结点压入队列中;
2,current() ==> 访问队头元素指向的数据元素;
3,next() ==> 队头元素弹出,将队头元素的孩子压入队列中(核心);
4,end() ==> 判断队列是否为空;
6,层次遍历算法示例:
7,层次遍历算法代码实现:
1 bool begin() // 为树中结点的遍历做初始化 2 { 3 bool ret = (root() != NULL); // 不能遍历空树 4 5 if( ret ) 6 { 7 m_queue.clear(); // 防止上一次没有调用完,这一次又调用,先清除;保证只有根结点; 8 m_queue.add(root()); // 添加根结点; 9 } 10 11 return ret; 12 } 13 14 bool end() // 队列长度为 0 则树遍历结束 15 { 16 return (m_queue.length() == 0); 17 } 18 19 bool next() // 队头元素弹出来,队头元素的孩子压入队列,同时指针一直指向下一个结点 20 { 21 bool ret = (m_queue.length() > 0); // 有元素才能移动游标 22 23 if( ret ) 24 { 25 GTreeNode<T>* node = m_queue.front(); // 将 node 指向对头元素 26 m_queue.remove(); // 队头元素拿出来,就指向了下一个结点 27 28 for(node->child.move(0); !node->child.end(); node->child.next()) // 出队列的结点(被 node 指向)的孩子压入队列 29 { 30 m_queue.add(node->child.current()); 31 } 32 } 33 34 return ret; 35 } 36 37 T current() // 返回当前游标所指向的结点的元素 38 { 39 if( !end() ) // 遍历结束,不指向目标 40 { 41 return m_queue.front()->value; // 将游标指向结点元素返回, front() 函数已经指向了当前的对象 42 } 43 else 44 { 45 THROW_EXCEPTION(InvalidOperationException, "No value at current position ..."); // 还没开始或者结束的非法操作 46 } 47 }
8,小结:
1,树的结点没有固定的编号方式;
2,可以按照层次关系对树中的结点进行遍历;
3,通过游标的思想设计遍历成员函数;
4,遍历成员函数是互相依赖,相互配合的关系;
5,遍历算法的核心为队列的使用;