题目一描述:不分行从上到下打印二叉树,即树的广度优先遍历

从上往下打印出二叉树的每个节点,同层节点从左至右打印。(不分行)

测试用例:

功能测试(完全二叉树;所有节点只有左/右子树的二叉树)

特殊输入测试(二叉树的根节点为nullptr;只有一个节点的二叉树

解题思路:

1)使用队列:

每次打印一个节点时,如果该节点有子节点,则把该节点的子节点放到一个队列的末尾。接下来到队列的头部取出最早进入队列的节点,重复前面的打印操作,直至队列中所有的节点都被打印出来。

//使用双向队列,用单向的队列就可以/*
struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;TreeNode(int x) :val(x), left(NULL), right(NULL) {}
};*/
class Solution {
public:vector<int> PrintFromTopToBottom(TreeNode* root) {vector<int> result;if(root==nullptr)return result;deque<TreeNode*> saveNodes;saveNodes.push_back(root);//error: while(saveNodes)  saveNodes没有对应的bool值while(!saveNodes.empty()){  //队列非空的时候   TreeNode* currNode = saveNodes.front();saveNodes.pop_front();result.push_back(currNode->val);if(currNode->left) //右子树非空,追加在队列的后面saveNodes.push_back(currNode->left);if(currNode->right) //左子树非空,追加在队列的后面saveNodes.push_back(currNode->right);}return result;}
};

//单向队列class Solution {
public:vector<int> PrintFromTopToBottom(TreeNode* root) {vector<int> result;if(root==nullptr)return result;queue<TreeNode*> saveNodes;saveNodes.push(root);//error: while(saveNodes)  saveNodes没有对应的bool值while(!saveNodes.empty()){  //队列非空的时候   TreeNode* currNode = saveNodes.front();saveNodes.pop();result.push_back(currNode->val);if(currNode->left) //右子树非空,追加在队列的后面saveNodes.push(currNode->left);if(currNode->right) //左子树非空,追加在队列的后面saveNodes.push(currNode->right);}return result;}
};  



题目二描述: 分行从上到下打印二叉树(把二叉树打印成多行)

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

解题思路:

1)为了分行打印,增加两个变量:一个变量表示在当前层中还没有打印的节点数;另一个变量表示下一层节点的数目。

class Solution {
public:vector<vector<int> > Print(TreeNode* pRoot) {vector<vector<int> > result;if(pRoot==nullptr)return result;vector<int> row;queue<TreeNode*> treeNodes;treeNodes.push(pRoot);int toBePrint = 1; //初始化为1,根节点int nextLevel = 0;while(!treeNodes.empty()){TreeNode* pNode = treeNodes.front();treeNodes.pop();row.push_back(pNode->val); toBePrint--;if(pNode->left){treeNodes.push(pNode->left);nextLevel++;}if(pNode->right){treeNodes.push(pNode->right);nextLevel++;}if(toBePrint==0){result.push_back(row);//删除行!!vector<int>().swap(row);toBePrint = nextLevel;nextLevel = 0;}}return result;}
}; 

错误的写法:

class Solution {
public:vector<vector<int> > Print(TreeNode* pRoot) {vector<vector<int> > result;if(pRoot==nullptr)return result;int row = 0;queue<TreeNode*> treeNodes;treeNodes.push(pRoot);int toBePrint = 1; //初始化为1,根节点int nextLevel = 0;while(!treeNodes.empty()){TreeNode* pNode = treeNodes.front();treeNodes.pop();(result[row]).push_back(pNode->val); //error: 不能这样使用 result[row].push_backtoBePrint--;if(pNode->left){treeNodes.push(pNode->left);nextLevel++;}if(pNode->right){treeNodes.push(pNode->right);nextLevel++;}if(toBePrint==0){row++;toBePrint = nextLevel;nextLevel = 0;}}return result;}
};

错误原因:

vector<vector<int> > result(10); (result[row]).push_back(pNode->val);   //可以使用 result[row]

但是若初始化时,没有指定vector的大小,则不能使用result[row],属于数组越界,非法访问。这种情况只能用push_back在尾部追加。

2)用队列的长度来记录每层的节点数

class Solution {
public:vector<vector<int> > Print(TreeNode* pRoot) {vector<vector<int> > result;if(pRoot == NULL) return result;queue<TreeNode*> q;q.push(pRoot);while(!q.empty()){ //每一个while循环打印一行int index = 0;  //用于遍历每行元素int numNodes = q.size();  //当前行的元素数==队列里的元素数vector<int> row; //用于存储每行的元素。while(index++ < numNodes){TreeNode *currNode = q.front();q.pop();row.push_back(currNode->val);if(currNode->left) q.push(currNode->left);if(currNode->right) q.push(currNode->right);}result.push_back(row);}return result;}
};



题目二描述: 按之字形打印二叉树

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

解题思路:

1)与分行打印树思路相同,只不过在偶数行时,将每行vector<int>倒序存入

class Solution {
public:vector<vector<int> > Print(TreeNode* pRoot) {vector<vector<int> > result;if(pRoot==nullptr)return result;queue<TreeNode*> treeNodes;treeNodes.push(pRoot);int count=1; //记录单行还是双行while(!treeNodes.empty()){vector<int> row; //用于存每行的元素 //每次循环都会被清零int numNodesInRow = treeNodes.size();  //每行元素的个数while(numNodesInRow--){TreeNode* curr = treeNodes.front(); //访问treeNodes.pop(); //删除row.push_back(curr->val);  //读取当前节点的元素if(curr->left)treeNodes.push(curr->left);if(curr->right)treeNodes.push(curr->right);}if((count & 0x1)==1){//第几行result.push_back(row);}else{vector<int> inverseRow(row.rbegin(),row.rend());result.push_back(inverseRow);}count++;}return result;}};

 * 大家的实现很多都是将每层的数据存进ArrayList中,偶数层时进行reverse操作,
 * 在海量数据时,这样效率太低了。
 * (我有一次面试,算法考的就是之字形打印二叉树,用了reverse,
 * 直接被鄙视了,面试官说海量数据时效率根本就不行。

2)使用两个栈:(不必将每层的数据存进queue中,偶数层时进行reverse操作,直接按打印顺序存入

在打印某一层节点时,把下一层子节点保存到相应的栈中。如果当前打印的时奇数层,从左到右打印,并先保存左子节点再保存右子节点到第一个栈中(奇数栈);如果当前打印的是偶数层,从右向左打印,并先保存右子节点再保存左子节点到第二个栈中(偶数栈)。  

//实现1class Solution {
public:vector<vector<int> > Print(TreeNode* pRoot) {vector<vector<int> > result;if(pRoot==nullptr)return result;//使用两个栈存储stack<TreeNode*> oddRow,evenRow;vector<int> row; //存储每行的遍历元素int numRow = 1;evenRow.push(pRoot);while(oddRow.size() || evenRow.size()){//两个栈有一个非空时,进入循环if((numRow & 0x1)==1){ //奇数行 从左到右 且先遍历左子树while(evenRow.size()){TreeNode* pNode = evenRow.top();evenRow.pop();row.push_back(pNode->val);if(pNode->left)oddRow.push(pNode->left);if(pNode->right)oddRow.push(pNode->right);}}else{ //偶数行 从右到左 且先遍历右子树while(oddRow.size()){TreeNode* pNode = oddRow.top();oddRow.pop();row.push_back(pNode->val);if(pNode->right)evenRow.push(pNode->right);if(pNode->left)evenRow.push(pNode->left);}}//遍历完一行result.push_back(row);vector<int>().swap(row);  //将row清空,便于下一行的存储numRow++;}return result;}};

//实现2
class Solution {
public:vector<vector<int> > Print(TreeNode* pRoot) {vector<vector<int> > result;if(pRoot==nullptr)return result;//使用两个栈存储stack<TreeNode*> levels[2];vector<int> row; //存储每行的遍历元素int current = 0;int next = 1;levels[current].push(pRoot);  //while(levels[0].size() || levels[1].size() ){TreeNode* pNode = levels[current].top(); //读取当前节点levels[current].pop();  //删除读取过的节点row.push_back(pNode->val);if(current==0){ //奇数行,先存左子树if(pNode->left)levels[next].push(pNode->left);if(pNode->right)levels[next].push(pNode->right);}else{ //偶数行,先存右子树if(pNode->right)levels[next].push(pNode->right);if(pNode->left)levels[next].push(pNode->left);}if(levels[current].empty()){ //当前栈为空时,换栈result.push_back(row);vector<int> ().swap(row); //清空rowcurrent = 1 - current;  //交换栈next = 1 - next;}}return result;}};

  

  

  

  

转载于:https://www.cnblogs.com/GuoXinxin/p/10449582.html

32 从上到下打印二叉树(举例让抽象问题具体化)相关推荐

  1. 剑指 Offer 32 . 从上到下打印二叉树

    main函数测试代码: 按标准输入输出,比如输入: 3,9,20,null,null,15,7 public static void main(String[] args) {//输入3,9,20,n ...

  2. 剑指offer——32.从上到下打印二叉树

    题目: 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 知识点: 像这种不是按照指针顺序打印的都需要引入辅助空间,由于分析可知,先进先出,因此我们引入了两端都可进出的队列deque,常用操作, ...

  3. 剑指offer 32. 从上到下打印二叉树

    声明:本系列博客是对何海涛<剑指offer>的关键点总结. 1.不分行从上到下打印二叉树 1.1. 问题描述 从上到下打印出二叉树的每一个结点,同一层的结点按照从左到右的顺序打印. 如二叉 ...

  4. 32. 从上到下打印二叉树 Ⅰ

    描述 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 示例 例如: 给定二叉树: [3,9,20,null,null,15,7], 返回:[3,9,20,15,7] 思路 此题考 ...

  5. Leetcode题库 32.从上到下打印二叉树(层次遍历 C实现)

    文章目录 解析 思路 改进 代码 解析 Queue为储存节点队列 Q_pos指向Queue尾部 Q_pri指向Queue头部 ret数组储存节点val值 *returnSize指向数组尾部 思路 先将 ...

  6. LeetCode-剑指 Offer 32 - I. 从上到下打印二叉树

    剑指 Offer 32 - I. 从上到下打印二叉树 思路一:BFS广度优先遍历 1: 定义一个res返回值 2:定义一个队列,先把头节点压入队列 3:while循环判断队列是否为空不为空进入循环 4 ...

  7. leetcode 打印_剑指 Offer 32 - III 从上到下打印二叉树 III - leetcode 剑指offer

    题目难度: 中等 原题链接 今天继续更新剑指 offer 系列, 这道题相比昨天那道题多了个每层打印方向不同的需求, 聪明的你想到应该如何实现了吗? 老样子晚上 6 点 45 分准时更新公众号 每日精 ...

  8. 32 - II. 从上到下打印二叉树 II

    链接 https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/ 难度: #简单 题目 从上到下按层打 ...

  9. 32 - I. 从上到下打印二叉树

    链接 https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/ 难度: #中等 题目 从上到下打印出二叉树 ...

  10. 【LeetCode】剑指 Offer 32 - III. 从上到下打印二叉树 III

    [LeetCode]剑指 Offer 32 - III. 从上到下打印二叉树 III 文章目录 [LeetCode]剑指 Offer 32 - III. 从上到下打印二叉树 III package o ...

最新文章

  1. 【Qt】QT_BEGIN_NAMESPACE 和 QT_END_NAMESPACE
  2. 单链表:头结点和头指针的实现方式
  3. AngularJs学习笔记--expression
  4. echarts格式化tooltip数据
  5. 001_docker-compose构建elk环境
  6. 十大WordPress安全设置技巧
  7. 服务器iis如何开启tlsv1.2协议,Windows系统中IIS启用TLS 1.2
  8. centos修改主机名的正确方法
  9. Python——(Anaconda+PyCharm)Youki的Python环境配置笔记(Windows版本)(legacy)~
  10. Android-JNI开发系列《八》CMakeLists.txt语法使用
  11. win10安装nvidia驱动
  12. Q学习(Q-learning)入门小例子及python实现
  13. 51单片机温控风扇仿真原理图 C语言程序,51单片机温控风扇仿真原理图+C语言程序与实物制作...
  14. 【文章整理】一文看懂Cola架构和DDD
  15. URP管线下使用Dither做像素化风格
  16. 利用sqlmap注入获取网址管理员账号密码
  17. android ListView中含有按钮事件实时更新ListView数据案例-1
  18. win 访问linux加密硬盘分区,手把手教你使用BitLocker给win10硬盘分区加密的方法
  19. 记参加哈工大SCIR(赛尔)实验室笔试
  20. 计算方法 7.数值积分计算方法

热门文章

  1. nyoj--38--布线问题
  2. 深入理解Java8 Lambda表达式
  3. C# 两个datatable中的数据快速比较返回交集或差集
  4. 高通RFC适配RFFE-添加MIPI设备【转】
  5. [清华集训2016]温暖会指引我们前行——LCT+最大生成树
  6. Android Handler机制之总目录
  7. Day4 单用户模式、救援模式、克隆虚拟机、linux机器相互登录
  8. 基于Hexo+Node.js+github+coding搭建个人博客——基础篇
  9. XVII Open Cup named after E.V. Pankratiev. GP of Siberia, Division 1
  10. C/C++学习路线(总体把握C/C++)