题目:二叉树的层次遍历
给定一棵二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号。
例如:
给定二叉树:
1 / \ 2 3 / \ \ 4 5 6 / \ 7 8
返回其层次遍历结果:
[ [1], [2,3], [4,5,6], [7,8] ]
解答:
①这道题难点在于分层输出,在遍历当前层的时候,保存下一层的节点数,需要每次插入一个节点的时候childSize++。
②明确下一层有几个节点,然后将childSize赋值给parentSize,开始新的一层遍历,从队列中取出parentSize个节点以后,也就知道这一层遍历完了。
③把一个结束信号放进队列里。由于使用queue<Node*>,可以插入一个空指针去表示一层的遍历结束。
代码示例:
1.节点的定义:
结构体:struct
struct Node
{
Node *pLeft;
Node *pRight;
int data;
};
分析:定义节点,及其向下的左右
2.头文件
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
分析:
①#include <algorithm> 调用C++算法库
②#include<queue> 队列容器
这个头文件定义了两个跟队列有关的类----quque、priority_queue,分别实现的是队列 和 优先队列这两个概念。与其它类模版(vector、array等)最大的不同是,它们是容器适配器。
分享一个demo—#include<queue>
#include <iostream>
#include <queue>
using namespace std; //这几个头文件必不可少
int main()
{
queue<int> q; //使用前需定义一个queue变量,且定义时已经初始化
while(!q.empty()) q.pop(); //重复使用时,用这个初始化
q.push(1); //进队列
q.pop(); //出队列
int v=q.front(); //对象.成员 得到队首的值
int s=q.size(); //对象.成员函数 得到队列里元素个数
return 0;
}
3.核心代码一
void Link(Node *nodes, int parent, int left, int right)
{
if (left != -1)
{
nodes[parent].pLeft = &nodes[left];
}
if (right != -1)
{
nodes[parent].pRight = &nodes[right];
}
}
分析:该函数作用是是将我们主函数里面的变量构造成二叉树形式,方便void PrintNodeByLevel(Node *root)函数调用。
示例:Link(test1, 1, 2, 3); void Link(Node *nodes, int parent, int left, int right)
该节点,分别将左右两个数放入相对位置
3.核心代码二
void PrintNodeByLevel(Node *root)
{
int parentSize = 1, childSize = 0;
Node * temp;
queue<Node *> q;//使用前需定义一个queue变量,且定义时已经初始化
q.push(root); //进队列
do
{
temp = q.front();//对象.成员 得到队首的值
cout << temp->data << " ";
q.pop(); //出队列
if (temp->pLeft != NULL)
{
q.push(temp->pLeft);//进队列
childSize++;
}
if (temp->pRight != NULL)
{
q.push(temp->pRight);//进队列
childSize++;
}
parentSize--;
if (parentSize == 0)
{
parentSize = childSize;
childSize = 0;
cout << endl;
}
} while (!q.empty());
}
分析:通过do while循环进行遍历,while(!q.empty()) 就是循环对队列进行某种操作,当队列为空的时候就停下来。 三个if()函数就是向队列中添加数字和对应长度自加一,并且当发现空指针(结束信号)时,要检查队列内是否还有节点,保护。
4.主函数
int main(int argc, char* argv[])
{
Node test1[9] = { 0 };
int i;
for (i = 0; i < 9; i++)
{
test1[i].data = i;
}
Link(test1, 1, 2, 3);
Link(test1, 2, 4, 5);
Link(test1, 3, -1, 6);
Link(test1, 5, 7, 8);
PrintNodeByLevel(&test1[1]);
return 0;
}
分析:定义变量,引用函数进行处理,输出结果。
该题所有测试代码如下
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
struct Node
{
Node *pLeft;
Node *pRight;
int data;
};
void Link(Node *nodes, int parent, int left, int right);
void PrintNodeByLevel(Node *root);
int main(int argc, char* argv[])
{
Node test1[9] = { 0 };
int i;
for (i = 0; i < 9; i++)
{
test1[i].data = i;
}
Link(test1, 1, 2, 3);
Link(test1, 2, 4, 5);
Link(test1, 3, -1, 6);
Link(test1, 5, 7, 8);
PrintNodeByLevel(&test1[1]);
return 0;
}
void Link(Node *nodes, int parent, int left, int right)
{
if (left != -1)
{
nodes[parent].pLeft = &nodes[left];
}
if (right != -1)
{
nodes[parent].pRight = &nodes[right];
}
}
void PrintNodeByLevel(Node *root)
{
int parentSize = 1, childSize = 0;
Node * temp;
queue<Node *> q;//使用前需定义一个queue变量,且定义时已经初始化
q.push(root); //进队列
do
{
temp = q.front();//对象.成员 得到队首的值
cout << temp->data << " ";
q.pop(); //出队列
if (temp->pLeft != NULL)
{
q.push(temp->pLeft);//进队列
childSize++;
}
if (temp->pRight != NULL)
{
q.push(temp->pRight);//进队列
childSize++;
}
parentSize--;
if (parentSize == 0)
{
parentSize = childSize;
childSize = 0;
cout << endl;
}
} while (!q.empty());
}