二叉树的层次遍历 C++算法 leetcode102(改)

题目:二叉树的层次遍历

给定一棵二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号。

例如:
给定二叉树: 

     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;
}

分析:定义变量,引用函数进行处理,输出结果。

写的代码都在VS2015下测试没有问题,输出结果为

该题所有测试代码如下

#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());	
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值