1. 问题描述
使用队列作为辅助存储,按树的结点的深度,从根开始依次访问所有结点。
2.问题分析与算法描述
所谓层序遍历,就是按照二叉树的节点深度,将处于每一层,也就是节点深度相同的节点按照从左到右的顺序依次访问。我们之前所做的先序遍历,中序 以及后序遍历可以通过递归以及调整访问的顺序即可实现,但是层序遍历则不行,层序遍历必须要从上到下,从左到右依次访问,递归的话会倒序访问也就 是直到递归结束时回溯访问,这显然实现层序遍历是不行的,对于一课树当我们访问到一个节点是如果这个节点比其他节点先访问,则他的儿子也一定比其 他节点的儿子优先访问,这样我们就可以在访问一个节点的时候把他的左儿子右儿子一次保存,然后访问下一个节点的时候我们就从保存的节点中取出访 问,知道把所有的节点“存储-访问”完成为止。这就要求我们的所用的辅助存储结构能够先存储的先访问,这种特点就可以用用队列满足。
下面是算法步骤:
1)根节点入队
2)将节点出队,如果该节点有儿子,按照从左到右的顺序入队
3)判断队列是否为空,若为空,则访问结束,否则转到2
3.算法实现
由于要用到队列,按照算法的设计,需要用到队列的入队,出队,以及为空判断的操作,由于不同的树的高度未知,每一层的节点数量不同,因此入队的节点的个数就不确定。我们可以通过循环利用队列来尽可能的充分利用队列的存储空间,这种循环可以通过对队列的空间长度取余实现
下面是实现队列相关操作的例程:
/*
*功能:二叉树的层序遍历
*作者:KDF5000
*时间:2013.1.18
*/
#include<stdio.h>
#include<stdlib.h>
typedef struct treeNode *Node;
struct treeNode{
int element;
treeNode *left;
treeNode *right;
};
struct Queue{
int size;
int head;
int tail;
treeNode *que;
};
Queue * initQueue(int qSize)
{
Queue *Q;
Q=(Queue *)malloc(sizeof(Queue));
Q->size=qSize;
Q->que=(treeNode *)malloc(sizeof(treeNode)*qSize);
Q->head=qSize;
Q->tail=0;
return Q;
}
//判断队列是否为空
int isEmpty(Queue *Q)
{
return Q->head%(Q->size)==Q->tail;
}
//入队
void pushQue(Queue *Q,treeNode *p)
{
*(Q->que+Q->tail++)=*p;
Q->tail %=Q->size;
}
//出队
treeNode * popQue(Queue *Q)
{
Q->head %=Q->size;
return Q->que+(Q->head ++);
}
//层序遍历
void traverse(treeNode *tree)
{
Queue *Q=NULL;
treeNode *p;
Q=initQueue(20);
pushQue(Q,tree);
printf(" [");
while(!isEmpty(Q))
{
p=popQue(Q);
printf("%d,",p->element);
if(p->left!=NULL)
pushQue(Q,p->left);
if(p->right!=NULL)
pushQue(Q,p->right);
}
printf("]\n");
}
//插入节点
treeNode *insert(treeNode *tree,int element)
{
if(tree==NULL)
{
treeNode *newNode=(treeNode *)malloc(sizeof(treeNode));
if(newNode==NULL)
return newNode;
newNode->element=element;
newNode->left=NULL;
newNode->right=NULL;
tree=newNode;
return tree;
}
if(tree->element>=element)
tree->left=insert(tree->left,element);
else
tree->right=insert(tree->right,element);
return tree;
}
//构造一个二叉树amount为想要随机生成的二叉树的节点个数
treeNode * creatTree(int amount)
{
treeNode *tree=NULL;
for(int i=0;i<amount;i++)
{
tree=insert(tree,rand()%50);
}
return tree;
}
//先序输出
void outputPre(treeNode * tree)
{
if(tree==NULL)
printf("空树!!!");
else
{
printf("%d,",tree->element);
if(tree->left!=NULL)
outputPre(tree->left);
if(tree->right!=NULL)
outputPre(tree->right);
}
}
//中序输出所有节点
void outputMid(treeNode *tree)
{
if(tree==NULL)
printf("空树!!!");
else
{
if(tree->left!=NULL)
outputMid(tree->left);
printf("%d,",tree->element);
if(tree->right!=NULL)
outputMid(tree->right);
}
}
void main()
{
treeNode *tree=creatTree(10);
if(tree==NULL)
return;
printf("先序遍历结果:\n");
printf(" [");
outputPre(tree);
printf("]\n");
printf("中序遍历结果:\n");
printf(" [");
outputMid(tree);
printf("]\n");
printf("层序遍历结果:\n");
traverse(tree);
}
5.实际运行结果
下面是随机构造的一个节点数为10 的二叉树的遍历结果: