剑指offer面试题32——从上到下打印二叉树

题目一:不分行从上到下打印二叉树

从上到下打印二叉树的每个节点,同一层的节点按照从左往右的顺序打印。其实就是二叉树的层序遍历。

 

思路:

      这道题要求的就是二叉树的层序遍历序列,之前PAT上面做过这样的题,其实就是利用的BFS(广度优先搜索)来做。建立一个队列,将二叉树的根节点先入队,然后输出根节点的值并且将根节点出队,这个时候判断根节点是否有左右子孩子,如果有就按照先左孩子再右孩子的顺序将它的孩子节点入队。然后出队第一个孩子节点输出它的值,并且将它出队,判断它有没有子孩子,如果有就从左往右入队,这样直到队列里面的元素为空的时候就完成了二叉树的层序序列输出。其实这里用queue就可以解决问题了,deque和queue的区别在于前者可以从两端读取和加入数据,但是后者只能从后端加入数据。

 

代码:

struct  BinaryTreeNode
{
	int  m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};
void PrintFromTopToBottom(BinaryTreeNode* pTreeRoot)
{
	if (!pTreeRoot)
		return;
	deque<BinaryTreeNode*>dequeTreeNode;
	dequeTreeNode.push_back(pTreeRoot);
	while (dequeTreeNode.size())
	{
		BinaryTreeNode* pNode = dequeTreeNode.front();
		dequeTreeNode.pop_front();
		printf("%d", pNode->m_nValue);
		if (pNode->m_pLeft)
			dequeTreeNode.push_back(pNode->m_pLeft);
		if (pNode->m_pRight)
			dequeTreeNode.push_back(pNode->m_pRight);
		
	}
}

复习:其实就是层次遍历,用广度优先搜索的方法来做就好了。

 

题目二:分行从上到下打印二叉树

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印一行。如下图所示:

8

6              10

5               7                9               11

 

思路:

         其实问题的核心还是层序遍历,只不过要按照层次分行来进行输出。可以这样想,定义两个变量,一个是当前层需要输出的节点个数ToBePrinted,另一个是下一层将要输出的节点个数nextLevel。首先初始化ToBePrinted=1,nextLevel=0。如果一个节点有子节点,则每把一个子节点加入队列,同时把变量nextLevel加1。每打印一个节点,ToBePrinted减1.当ToBePrinted=0时,表示当前层的所有节点已经打印完毕,可以继续打印下一层。这一步很重要,当ToBePrinted=0的时候,将toBePrinted=nextLevel,同时把nextLevel=0,开始新的一轮遍历。

代码:

struct BinaryTreeNode
{
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

void Print(BinaryTreeNode* pRoot)
{
	if (pRoot == nullptr)
		return;

	queue<BinaryTreeNode*>nodes;
	nodes.push(pRoot);
	int nextLevel = 0;
	int toBePrinted = 1;
	while (!nodes.empty())
	{
		BinaryTreeNode* pNode = nodes.front();
		printf("%d", pNode->m_nValue);
		if (pNode->m_pLeft)
		{
			nodes.push(pNode->m_pLeft);
			++nextLevel;
		}
		if (pNode->m_pRight)
		{
			nodes.push(pNode->m_pRight);
			++nextLevel;
		}
		nodes.pop();
		--toBePrinted;
		if (toBePrinted == 0)
		{
			printf("/n");
			toBePrinted = nextLevel;
			nextLevel = 0;
		}

	}
	
}

复习:这道题得定义好当前要打印的层次节点数和下一层次要打印的节点数,顺序不要乱。

 

题目三:之字形打印二叉树。

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行依次类推。如下图所示。

 

1

3            2

4            5           6           7

15          14         13         12          11         10           9          8

思路:

         首先还是用队列来思考,将1入队并且出队,然后先入队右孩子3再入队左孩子2,这个时候出队3,入队7和6,再出队2,入队5和4,这时候队列里面是{7 6 5 4},队首为7,而题目要求输出4,即后进的数据先输出,这个时候就想到了栈。这里建立两个栈,首先在第一个栈里面入栈1,然后打印并且出栈1,接着在另一个栈里面入栈1的左孩子2和右孩子3(注意这里的顺序,先左后右,这样出栈就是先右后左);这个时候第二个栈出栈并且输出3,在第一个栈里面入栈右孩子7和左孩子6(注意这里的顺序,先右后左,这样出栈就是先左后右),再出栈并且输出2,在一个栈里面入栈5和4,这样第二个栈就为空,第一个栈里面的元素就是{4 5  6 7},4为栈首元素。依此类推,奇数层和偶数层入栈的顺序使相反的,这样就可以按照要求输出二叉树。

 

 

代码:

struct BinaryTreeNode
{
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

void Print(BinaryTreeNode* pRoot)
{
	if (pRoot == nullptr)
		return;

	stack<BinaryTreeNode*>levels[2];//*号别掉了
	int current = 0;
	int next = 1;
	
	levels[current].push(pRoot);

	while (!levels[0].empty()||!levels[1].empty())
	{
		BinaryTreeNode* pNode = levels[current].top();
		levels[current].pop();

		printf("%d", pNode->m_nValue);

		if (current == 0)
		{
			if (pNode->m_pLeft != nullptr)
				levels[next].push(pNode->m_pLeft);
			if (pNode->m_pRight != nullptr)
				levels[next].push(pNode->m_pRight);
		}
		else {
			if (pNode->m_pRight != nullptr)
				levels[next].push(pNode->m_pRight);
			if (pNode->m_pLeft != nullptr)
			{
				levels[next].push(pNode->m_pLeft);
			}
		}

		if (levels[current].empty())
		{
			printf("\n");
			current = 1 - current;
			next = 1 - next;
		}
	}





}

复习:

主要是辅助栈的运用,这种题就要动手多模拟,分析输入输出的先后顺序。

二刷代码:

struct BinaryTreeNode
{
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

void Print(BinaryTreeNode* pTreeRoot)
{
	if (pTreeRoot == nullptr)
		return;

	stack<BinaryTreeNode*>levels[2];
	int current = 0;
	int next = 0;

	while (!levels[0].empty()||!levels[1].empty())
	{
		BinaryTreeNode* pNode = levels[current].top();
		levels[current].pop();
		printf("%d", pNode->m_nValue);

		if (current == 0)
		{
			if (pNode->m_pLeft != nullptr)
				levels[1].push(pNode->m_pLeft);

			if (pNode->m_pRight!=nullptr)
				levels[1].push(pNode->m_pRight);
		}
		else
		{
			if (pNode->m_pRight != nullptr)
				levels[1].push(pNode->m_pRight);
			if (pNode->m_pLeft != nullptr)
				levels[1].push(pNode->m_pLeft);
		}
		if (levels[current].empty())
		{
			printf("\n");
			current = 1 - current;
			next = 1 - next;
		}
	}


}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值