版权声明:本文为博主原创学习笔记,如需转载请注明来源。 https://blog.csdn.net/SHU15121856/article/details/82584815
面试题32-2:分行层序打印二叉树
从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行。
分行打印,用两个变量一个指示当前行结点数,一个指示下一行结点数。在队列里入栈和出栈时就能维护了。当前行走到0就打完了一行,换行把下一行拿上来。
#include<bits/stdc++.h>
#include "..\Utilities\BinaryTree.h"
using namespace std;
//层序遍历分行打印二叉树
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 != nullptr) {
nodes.push(pNode->m_pLeft);
++nextLevel;//压入同时将下层结点数+1
}
//判空并压入右子结点
if(pNode->m_pRight != nullptr) {
nodes.push(pNode->m_pRight);
++nextLevel;//压入同时将下层结点数+1
}
//弹出刚刚输出过的队头,并将本层节点数-1
nodes.pop();
--toBePrinted;
//[关键]两个变量相互维护
//如果本层节点数减少到了0
if(toBePrinted == 0) {
printf("\n");//那么说明本层已经打印完了,要打印下一层了
toBePrinted = nextLevel;//将下层结点数复制到本层
//因为这一次循环一定是出队了"本层"的最后一个结点
//同时将其携带的"下层"结点入队
//而这几个结点入队以后"下层"结点就全部入完队了
//并且没有"下下层"的结点
nextLevel = 0;//所以此时将下层节点数设置为0
}
}
}
// 8
// 6 10
// 5 7 9 11
int main() {
BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
BinaryTreeNode* pNode9 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNode11 = CreateBinaryTreeNode(11);
ConnectTreeNodes(pNode8, pNode6, pNode10);
ConnectTreeNodes(pNode6, pNode5, pNode7);
ConnectTreeNodes(pNode10, pNode9, pNode11);
Print(pNode8);
DestroyTree(pNode8);
return 0;
}
面试题32-3:分行层序之字形打印二叉树
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
之字形要用两个栈,一层从左往右进,一层从右往左进。出栈时一个出完再出下一个。
#include<bits/stdc++.h>
#include "../Utilities/BinaryTree.h"
using namespace std;
//输入树根,层序之字形打印二叉树
void Print(BinaryTreeNode* pRoot) {
if(pRoot == nullptr)//非空校验
return;
//创建两个栈,分别用来保存之字型的两个顺序
//在之前写层序遍历中,一个队列里也最多只能出现相邻两层的结点
//所以两个栈足够用,分别各自交替存放一层的结点(入栈顺序相反),再各自pop至空
stack<BinaryTreeNode*> levels[2];
//结合上一道题:按行层序打印二叉树,需要使用两个变量维护
int current = 0;//当前所在栈号,0栈放偶数层
int next = 1;//下一层应放在栈号,1栈放奇数层
levels[current].push(pRoot);//树根压入0号(偶数层)栈
//只要两个栈都不是空,则逻辑队列非空
while(!levels[0].empty() || !levels[1].empty()) {
//取当前层栈顶元素
BinaryTreeNode* pNode = levels[current].top();
levels[current].pop();
printf("%d ", pNode->m_nValue);//层内输出
//如果当前在0号栈(偶数层栈)
if(current == 0) {
//孩子以先左再右的顺序入1号栈(奇数层栈)
if(pNode->m_pLeft != nullptr)
levels[next].push(pNode->m_pLeft);
if(pNode->m_pRight != nullptr)
levels[next].push(pNode->m_pRight);
}
//如果当前在1号栈(奇数层栈)
else {
//孩子以先右再左的顺序入0号栈(偶数层栈)
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");//换行
//换栈,下次循环要打印的是另一个栈了
//下面的操作就是0变1,1变0
current = 1 - current;
next = 1 - next;
}
}
}
// 8
// 6 10
// 5 7 9 11
int main() {
BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
BinaryTreeNode* pNode9 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNode11 = CreateBinaryTreeNode(11);
ConnectTreeNodes(pNode8, pNode6, pNode10);
ConnectTreeNodes(pNode6, pNode5, pNode7);
ConnectTreeNodes(pNode10, pNode9, pNode11);
Print(pNode8);
DestroyTree(pNode8);
return 0;
}