【二叉树2】逐层遍历一棵二叉树

【问题描述】

对【二叉树1】中建立的二叉树逐层打印,也就是说第一行打印第0层根节点,第二行打印第一层……如此类推。

【举例】

一棵二叉树如下:

打印结果为:


【代码】

编程之美介绍了两种实现,一种是递归,该方法需要一个层数作为参数。

另一种就是如下方法,用两个游标记录树的每一层。

代码仅为该函数的实现,和所需头文件。并且不包含二叉树节点的定义以及main函数的调用

#include <iostream>
#include <vector>
using namespace std;

void PrintBTreeByLevel(BTreeNode *root){
	if(root==NULL)
		return;
	vector<BTreeNode*> vec;
	vec.push_back(root);
	int current=0,last=1;
	while(current<vec.size())
	{
		while(current<last)
		{
			cout<<vec[current]->value<<" ";
			if(vec[current]->leftchild)//A
				vec.push_back(vec[current]->leftchild);
			if(vec[current]->rightchild)//B
				vec.push_back(vec[current]->rightchild);
			++current;			
		}
		last=vec.size();
		cout<<endl;
	}

}

做leetcode的时候发现上述代码超出内存限制,主要原因在vector中存放了所有的节点,最好选取queue来存放节点,每次只存放一层。还有leetcode函数输出为一个二维的vector,不是单纯打印,所以稍稍复杂。

有三种思路:

【思路一】用一个NULL做分隔

vector<vector<int> > levelOrder(TreeNode *root) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function
    vector<vector<int>> levels;
    queue<TreeNode *> que;
    if (!root)
        return levels;
    que.push(root);
    que.push(NULL);
    
    while(que.front() != NULL) {
        vector<int> line;
        TreeNode *temp = que.front();
        que.pop();
        while (temp != NULL) {
            line.push_back(temp->val);
            if (temp->left)
                que.push(temp->left);
            if (temp->right)
                que.push(temp->right);
            temp = que.front();
            que.pop();
        }
        
        levels.push_back(line);
        que.push(NULL);
        
    }
    return levels;
}

【思路二】申请一个附加容器,存储当前层的下一层,然后将下一层再拷贝回queue

vector<vector<int> > levelOrder(TreeNode *root) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function
    vector<vector<int>> levels;
    queue<TreeNode *> q;
    if (!root)
        return levels;
    q.push(root);
    while(!q.empty()) {
        vector<int> l;
        vector<TreeNode *> temp;
        while(!q.empty()) {
            TreeNode *p = q.front();
            q.pop();
            l.push_back(p->val);
            if (p->left) temp.push_back(p->left);
            if (p->right) temp.push_back(p->right);
        }
        levels.push_back(l);
        for (int i=0; i<temp.size(); i++)
            q.push(temp[i]);
    }
    return levels;
}


【思路三】递归的方法,函数travers是一个top-buttom的方法,算法很简单很奇妙,是leetcode上的大牛写的。简单理解一下:

if (level > result.size())

判断result中是否出现过这一层的元素。root='a'时,level=1,result.size()=0,说明遍历到第一层时,result还是空的,所以需要需要push进去一个vector<int>;root=’b'时,level=2,result.size()=1,继续push;root='c'时,level=2,result.size()=2,直接执行后面的语句。

result[level-1].push_back(root->val)

因为result是从0开始的,level是从1开始的,所以需要result[level-1]进行push

vector<vector<int> > levelOrderBottom(TreeNode *root) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function
    vector<vector<int>> result;
    traverse(root, 1, result);
    std::reverse(result.begin(), result.end());
    return result;
}

void traverse(TreeNode *root, int level, vector<vector<int>> &result) {

    if (!root)
        return;

    if (level > result.size()) {
        vector<int> temp;
        result.push_back(temp);
    }
    result[level-1].push_back(root->val);
    traverse(root->left, level+1, result);
    traverse(root->right, level+1, result);
}



【扩展一】打印一棵二叉树的镜像

只需要交换上述代码中A和B的两段if,也就是先让一个节点的右孩子入栈,再让左孩子入栈,结果如下:

【扩展二】从下到上逐层打印二叉树

可以在正向遍历的结果后加上一句std::reverse(result.begin(),result.end())做反转

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值