关于二叉树的遍历,大家肯定都不会陌生。当然,这种题目很多人都会做,但是你们心中的解题办法是不是够漂亮呢?
首先,这里需要用到的数据结构的队列,这应该没有什么疑问,先进先出嘛。子节点在父节点之后,而用队列,子节点是通过父节点入队列,所以在父节点之后,OK~符合标准!先来说说大致的一些解题思路。
1、在NODE的定义中定义一个flag标记,用来记录该节点属于哪一层,然后如果当前节点的层数大于上一个节点的层数,那就在打印这个节点之前打印一个换行符。但是这样做有什么不好呢?在NODE的定义中加入flag标记,这样会使我们定义的数据类型过于庞大,这肯定是不好的。
2、当然如果不能在NODE里面定义一个flag标记,也可以,那就利用一个辅助的队列来表明当前节点所属的层数。其实上面这两种思想在面试100题系列之11在树中找到符合条件的路径里面有反映。当然,在那里,用辅助栈的思想是比较好的,但是这里,情况又不是完全一样,有没有可能说除了一个队列之外,不需要其他的辅助内存呢??可以做到么?答案是肯定的。
3、那如果不用辅助内存怎么做?初始的状态只有根节点会在队列里面,OK,其余所有的节点都是通过根节点进来的,而且每次遍历其实只要控制得好,是可以让节点一层一层进来的,怎么做?
用一个Begin记下这一层的开始,End记下这一层的结尾,OK,通过Begin和End之间的节点进入队列的一定是下一层的节点。当Begin和End之间的节点访问完之后,打印一个换行符,进入下一层遍历,将Begin指向上一次的End+1,End指向新的NewEnd。然后依次循环下去。初始时刻,那就只有根节点在队列中,Begin=End=NewEnd=0。
参考代码:
//用数组来模拟队列
void PrintTreeByLevelWithArr(NODE *pRoot)
{
if(!pRoot)
return;
NODE *Queue[N];//N为预设的大小
int Begin = 0;
int End = 0;
int NewEnd = 0;
Queue[0] = pRoot;
while(Begin <= End)
{
while(Begin <= End)
{
printf("%d ", Queue[Begin]->data);
if(Queue[Begin]->Left)
Queue[++NewEnd] = Queue[Begin]->Left;
if(Queue[End]->Right)
Queue[++NewEnd] = Queue[Begin]->Right;
++Begin;
}
printf("\n");
End = NewEnd;
}
}
//用vector来模拟队列
void PrintTreeByLevelWithVec(NODE *pRoot)
{
if(!pRoot)
return;
//这里用vector来代替数组,利用其动态扩展的属性
vector<NODE *> vec;
int Begin = 0;
int End = 1;
vec.push_back(pRoot);
while(Begin < End)
{
while(Begin < End)
{
printf("%d ", vec[Begin]->data);
if(vec[Begin]->Left)
vec.push_back(vec[Begin]->Left);
if(vec[Begin]->Right)
vec.push_back(vec[Begin]->Right);
++Begin;
}
End = vec.size();
printf("\n");
}
}
最后,按照惯例,给出一些数据结构、变量的定义,以及main函数等:#include<stdio.h>
#include<vector>//vector所在的库文件
using namespace std;
struct NODE
{
int data;
NODE *Left;
NODE *Right;
};
const int N = 30;
NODE node[N];
int top;
//往二叉查找树里面加节点
void Add(NODE *root, int v)
{
if(!root)
return;
if(root->data < v)
{
if(root->Right)
Add(root->Right, v);
else
{
root->Right = &node[++top];
node[top].data = v;
}
}
else if(root->data > v)
{
if(root->Left)
Add(root->Left, v);
else
{
root->Left = &node[++top];
node[top].data = v;
}
}
else
printf("重复加入节点%d\n", v);
}
int main()
{
int n,i,v;
while(scanf("%d", &n) != EOF)
{
memset(node, 0, sizeof(node));
top = 0;//top是node数组的顶
scanf("%d", &v);
node[0].data = v;
for(i = 1; i < n; ++i)
{
scanf("%d", &v);
Add(&node[0], v);
}
PrintTreeByLevelWithArr(&node[0]);
PrintTreeByLevelWithVec(&node[0]);
}
}