树、森林的遍历与互转二叉树

要了解二叉树与树,森林的互转,首先要知道树的存储结构:

 

一个合理的想法是在结点中存放指向每一个子女结点的指针。但由于各个结点的子女数不同,每个结点设置数目不等的指针,将很难管理。


所以就有了

子女-兄弟表示(也称为树的二叉树表示。结点构造为)

firstChild 指向该结点的第一个子女结点。无序树时,可任意指定一个结点为第一个子女。
nextSibling 指向该结点的下一个兄弟。任一结点在存储时总是有顺序的。
若想找某结点的所有子女,可先找firstChild,再反复用 nextSibling 沿链扫描。

代码实现:树的表示(2)--子女兄弟表示法_KRYON!的博客-CSDN博客

template <class T>
struct TreeNode {			//树的结点类
     T data;				//结点数据
     TreeNode<T> *firstChild, *nextSibling;
 		                                         //子女及兄弟指针
    TreeNode (T value = 0, TreeNode<T> *fc = NULL,   
        TreeNode<T> *ns = NULL)     //构造函数
	    : data (value), firstChild (fc), nextSibling (ns) { }
};
template <class T>
class Tree {			//树类
private:
     TreeNode<T> *root, *current;				//根指针及当前指针
     int Find (TreeNode<T> *p, T value);			//在以p为根的树中搜索value
     void RemovesubTree (TreeNode<T> *p);		//删除以p为根的子树
     bool FindParent (TreeNode<T> *t, 
          TreeNode<T> *p);
public:
     Tree () { root = current = NULL; }	//构造函数
     bool Root ();	           //置根结点为当前结点
     bool IsEmpty () { return root == NULL; }
     bool FirstChild ();
	     //将当前结点的第一个子女置为当前结点
	 bool NextSibling ();
	     //将当前结点的下一个兄弟置为当前结点
     bool Parent ();
         //将当前结点的双亲置为当前结点
     bool Find (T value);
	     //搜索含value的结点, 使之成为当前结点
     …… 			//树的其他公共操作
};

template <class T> 
bool Tree<T>::Root () {
//让树的根结点成为树的当前结点
     if (root == NULL) {
          current = NULL;  return false;
     }
     else {
         current = root;  return true;
     }
};

template <class T> 
bool Tree<T>::Root () {
//让树的根结点成为树的当前结点
     if (root == NULL) {
          current = NULL;  return false;
     }
     else {
         current = root;  return true;
     }
};

template <class T>
bool Tree<T>::
FindParent (TreeNode<T> *t, TreeNode<T> *p) {
//在根为*t的树中找*p的双亲, 并置为当前结点
     TreeNode<T> *q = t->firstChild;     //*q是*t长子
     bool succ;
     while (q != NULL && q != p) {	  //扫描兄弟链
          if ((succ = FindParent (q, p)) == true) 
               return succ;	//递归搜索以*q为根的子树
          q = q->nextSibling;
     }
     if (q != NULL && q == p) {
          current = t;  return true;
     }
     else { current = NULL;  return false; }   //未找到
};

template <class T> 
bool Tree<T>::FirstChild () {
//在树中找当前结点的长子, 并置为当前结点
     if (current && current->firstChild )
         { current = current->firstChild;  return true; }
     current = NULL;  return false;
};

template <class T> 
bool Tree<T>::NextSibling () {
//在树中找当前结点的兄弟, 并置为当前结点
     if (current && current->nextSibling) {
          current = current->nextSibling;
          return true;
     }
     current = NULL;  return false;
};

转换概念有点抽象,我直接放大佬博客了

树、森林和二叉树的转换 - zhuyf87 - 博客园

把二叉树转换成树(代码实现)_追梦少年ML的博客-CSDN博客

树的遍历(通过子女兄弟法)

 

//算法实现
template <class T> 
void Tree<T>::
PreOrder ( void (*visit) (BinTreeNode<T> *t) ) {	
//以当前指针current为根, 先根次序遍历
     if (!IsEmpty ()) {         	//树非空
          visit (current);		//访问根结点
          TreeNode<T> *p = current;     //暂存当前指针
          current = current->firstChild;  //第一棵子树
          while (current != NULL) { 
               PreOrder (visit);	//递归先根遍历子树
               current = current->nextSibling;
          }
          current = p;			//恢复当前指针
     }
};

 

 代码实现

template <class T>
void Tree<T> :: 
PostOrder (void (*visit) (BinTreeNode<T> *t)) {
//以当前指针current为根, 按后根次序遍历树
     if ( ! IsEmpty () ) {                         //树非空
          TreeNode<T> *p = current;     //保存当前指针
          current = current->firstChild;   //第一棵子树 
          while (current != NULL) {        //逐棵子树	
               PostOrder (visit);
               current = current->nextSibling;
          }
          current = p;                                //恢复当前指针
          visit (current);                            //访问根结点
     }
};

 广度优先(树的层次遍历)

template <class T> 
void Tree<T>::
LevelOrder(void (*visit) (BinTreeNode<T> *t) ) {
//按广度优先次序分层遍历树, 树的根结点是
//当前指针current。
     Queue<TreeNode<T>*> Q;
     TreeNode<T> *p;
     if (current != NULL) { 	      //树不空 
          p = current;                             //保存当前指针
          Q.EnQueue (current);             //根结点进队列
          while (!Q.IsEmpty ()) {
               Q.DeQueue (current);        //退出队列
               visit (current);                    //访问之
               current = current->firstChild;
               while (current != NULL) { 
               Q.EnQueue (current);
               current = current->nextSibling;
               }
          }
          current = p;	  //恢复算法开始的当前指针
     }
};

 森林的遍历(无代码)

 

 

c语言多叉树转二叉树_lxy123go的博客-CSDN博客_c语言多叉树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值