层序遍历及其应用

来源:互联网 发布:im即时通讯源码java 编辑:程序博客网 时间:2024/09/21 09:20

层序遍历,利用队列存储下一层的节点,也就是说,队列中最多共存两层的节点。
具体说,根节点入队,出队,将其左右孩子入队。再出队,为根节点的左孩子(如果存在),将其左右孩子入队,再出队,为根节点的右孩子(如果存在)….

void levelorder(btree t){ initqueue(Q); btnode *p=t; if(p) enqueue(Q,p);// 根节点入队 while(!empty(Q)){  dequeue(Q,p);//出队  ------------------  visit(p);  ------------------  if(p->lchild) enqueue(Q,p->lchild);  if(p->rchild) enqueue(Q,p->rchild); }}

应用:
1.完全二叉树的判断
2.二叉树宽度
3.非递归二叉树深度
4.删除以x为根的子树
5.求二叉树的带权路径长度
6.之字形遍历二叉树
待补充

1.完全二叉树的判断
算法思想:将非空节点的左右孩子(包括空)全部入栈,若空,则判断之后的节点是否存在非空节点,若存在,则不是完全二叉树

bool iscomplete(btree t){  initqueue(Q); btree p=t; if(p) enqueue(Q,p); while(!empty(Q)){  dequeue(Q,p);  if(p){   enqueue(p->lchild);   enqueue(p->rchild);  } ------------------ //visit(p)部分 else  while(!empty(Q)){   dequeue(Q,p);   if(p) return false;//还存在非空节点,为非完全二叉树  } ------------------ }return true; //为完全二叉树}

2.求二叉树宽度
算法思想:设置last指针指向该层最右节点,levelsum[i]来记录第i层的节点数,m来记录最大宽度。扫描队首,levelsum[i]++,将其左右孩子(非空)入队,紧接着,判断队首元素是否为最右节点,若是,更新m,last(指向队尾即是),否则继续。直到队列为空

int width(btree t){ initqueue(Q,e); btree e=t,last=t;//初始化 int levelsum[maxsize]=0,i=0,m=0;//初始化 if(e) enqueue(Q,e); while(!empty(Q)){  dequeue(Q,e);  levelsum[i]++;   //e当前层节点数加1  if(e->lchild) enqueue(Q,e);  if(e->rchild) enqueue(Q,e);  -------------  //visit部分  if(e==last){   last=Q.data[rear];//更新last指向下一层最右节点,即队尾   m=m>levelsum[i]?m:levelsum[i];//更新m   i++;//更新i  }  -------------- } return m;//返回宽度最大值,即二叉树宽度}

3.非递归求二叉树深度
算法思想:即2.二叉树宽度中的i变量。

int depth(btree t){ initqueue(Q); btree e=t,last=e; int i=0; if(e) enqueue(Q,e); while(!empty(Q)){  dequeue(Q,e);  -------------------  //visit部分  if(e==last){   i++;   last=Q.data[rear];   }  --------------------  if(p->lchild) enqueue(Q,lchild);  if(p->rchild) enqueue(Q,rchild); } return i;//返回深度}

4.删除以x为根的子树
算法思想:
删除算法:采用后序遍历,先删除左右子树,再删除根节点
查找x节点:层次遍历,出队时判断是否为x,若是,则删除该子树。

void deletetree( btree t){ if(t){  deletetree(t->lchild);  deletetree(t->rchild); } free (t);}//删除算法bool delete_xtree(btree t,elemtype x){ initqueue(Q); btree e=t; if(e) enqueue(Q,e); while(!empty(Q)){  dequeue(Q,e);  --------------  //visit部分  if(e->data==x){   deletetree(e);   return true;//找到x并删除该子树,并返回  }  --------------  if(e->lchild) enqueue(Q,e);  if(e->rchild) enqueue(Q,e); }//whilereturn false;//没有找到x,返回}

5.求wpl(二叉树所有叶节点的带权路径长度和)
算法思想:二叉树节点信息data改为权值weight。层次遍历,并记录层数,遇到叶节点时,累加wpl。

typedef struct btnode{ int weight; struct btnode *lchild,*rchild;}*btree;int btree_wpl(btree t){   initqueue(Q); btree e=t,last=e; int level=0,wpl=0; if(e) enqueue(Q,e); while(!empty(Q)){  dequeue(Q,e);  ---------------------  //visit部分  if(e->lchild==null&&e->rchild==null){   wpl+=e->weight*level;  }  if(e==last){   level++;   last=Q.data[rear];  }  ---------------------  if(e->lchild) enqueue(e->lchild);  if(e->rchild) enqueue(e->rchild); } return wpl;}

6.之字形遍历二叉树
算法思想:记录当前层数,奇数层从左到右遍历,偶数层从右到左(使用栈),奇数层和偶数层的判断可以用一趟循环中遍历两层来实现。

void Z_oreder(btree t){initqueue(Q);initstack(S);btree e=t,last=e;if (e) enqueue(Q,e);while(!empty(Q)){//奇数层 while(e!=last){//遍历当前层  dequeue(Q,e);  visit(e);  if(e->lchild) enqueue(Q,e->lchild);  if(e->rchild) enqueue(Q,e->rchild); } visit(e);//访问最右节点 last=Q.data[rear];//更新下一层 //偶数层 while(e!=last){//遍历当前层  if(e->lchild) enqueue(Q,e->lchild);  if(e->rchild) enqueue(Q,e->rchild);  dequeue(Q,e);//出队  push(S,e);//入栈 } push(S,e);//将最右节点入栈 while(!emptystack(S)){  pop(S,e);//出栈  visit(e); }//逆序}//while}

希望大家指出错误,提供意见,补充扩展,谢谢!