《剑指offer》——栈的压入弹出序列、从上到下打印二叉树、分行从上到下打印二叉树、之字型打印二叉树

一、栈的压入、弹出序列

· 题目描述

        输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

· 解题思路

        本题考虑借用辅助栈。将第一个序列中所有元素先全部压入辅助栈中,然后再按照第二个序列的顺序依次从该栈中弹出。

        首先需要判断在第二个序列中下一个要弹出的元素是否是辅助栈的栈顶元素,如果是则直接弹出该元素;如果不是,则先把未入栈的数字压入辅助栈,知道把下一个需要弹出的数字压入辅助栈栈顶为止;如果所有元素压入仍未找到下一个弹出的数字,则该序列不是一个弹出序列。

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        stack<int>data; //定义辅助栈
        int num=0;       //pushV的栈顶指针
        for(int i=0;i<popV.size();i++)  //外层循环通过输出序列来控制
        {
            //填满辅助栈的情况
            while(data.size()==0||data.top()!=popV[i])
            {
                data.push(pushV[num++]); //这里是++num还是num++需要看选取的pushV的栈顶指针初值
                if(num>pushV.size())
                    return false;
            }
            data.pop();
        }
        if(data.size()==0)
            return true;
        else
            return false;
    }
};

二、从上到下打印二叉树

· 题目描述

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

· 解题思路

        本题应该考虑用队列来实现层次遍历。

class Solution {
public:
    vector<int> PrintFromTopToBottom(TreeNode* root) {
        vector<int>res;   //定义返回数组
        if(root==nullptr)
            return res;
        queue<TreeNode*>Q;//定义队列
        TreeNode* tmp;
        Q.push(root);     //保存根节点
        while(!Q.empty())
        {
            tmp=Q.front();  //根节点出队
            res.push_back(tmp->val);
            if(tmp->left!=nullptr) //左子树入队
                Q.push(tmp->left);
            if(tmp->right!=nullptr) //右子树入队
                Q.push(tmp->right);
            Q.pop();
        }
        return res;
    }
};

三、分行从上到下打印二叉树

· 题目描述

         从上到下按层打印二叉树,同一层的结点按照从左到右的顺序打印,每一层打印到一行。

· 解题思路

         本题依旧是采用队列来实现层次遍历,不同的是应该定义两个变量来存储上一行需要打印的结点数目(用来判断上一层是否打印完了)和下一行需要打印的结点数目(用来记录下一层需要打印的数目)。

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
//分层打印二叉树
//定义二叉树结构
struct TreeNode
{
	TreeNode* left;  //左子树
	TreeNode* right; //右子树
	int data;        //存储数据
};
class Solution
{
public:
	TreeNode* createTree();  //创建二叉树
	void PrintFromTopToBottom(TreeNode* root);
};
//输入序列要按照中序遍历的顺序来定义二叉树
TreeNode* Solution::createTree()
{
	TreeNode* node;
	int value;
	cout << "请输入结点值:";
	cin >> value;
	if (value == 0)
	{
		node = NULL;
	}
	else
	{
		node= (TreeNode*)malloc(sizeof(TreeNode));
		node->data = value;
		node->left = createTree();    //为左子树赋值
		node->right = createTree();   //为右子树赋值
	}	
	return node;
}
void Solution::PrintFromTopToBottom(TreeNode* root)
{
	//采用层次遍历分层打印二叉树
	vector<int>res;
	queue<TreeNode*>Q;
	if (root == nullptr)
		return;
	TreeNode* tmp;
	int high = 1;   //上一层
	int low = 0;    //下一层
	Q.push(root);
	while (!Q.empty())
	{
		tmp = Q.front();
		cout << tmp->data;
		if (tmp->left != nullptr)  //左子树入队
		{
			Q.push(tmp->left);
			low++;
		}
		if (tmp->right != nullptr)   //右子树入队
		{
			Q.push(tmp->right);
			low++;
		}
		Q.pop();
		high--;
		if (high == 0)
		{
			cout << endl;
			high = low;
			low = 0;
		}
	}
}
int main()
{
	TreeNode* root;
	Solution s;
	root=s.createTree();//创建二叉树
	s.PrintFromTopToBottom(root);  //分层打印
	system("pause");
	return 1;
}

四、之字型打印二叉树

· 题目描述

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

· 解题思路

        本题结合了上面两个题,首先需要定义连个栈:奇数栈先保存左子树再保存右子树的值,偶数栈则先保存右子树的值,再保存左子树的值。

void Solution::print(TreeNode* root)
{
	if (root == nullptr)
		return;
	stack<TreeNode*>level[2];   //定义两个数据栈,一个存放奇数层的值,另一个存放偶数层的值
	int current = 0;
	int next = 1;
	level[current].push(root);
	while (!level[0].empty() || !level[1].empty())
	{
		TreeNode* tmp = level[current].top();//赋值
		level[current].pop();      //出栈
		cout << tmp->data;
		//遍历奇数层
		if (current == 0)
		{
			//保存左子树
			if (tmp->left != nullptr)
				level[next].push(tmp->left);
			//保存右子树
			if (tmp->right != nullptr)
				level[next].push(tmp->right);
		}
		//遍历偶数层
		else
		{
			//保存右子树
			if (tmp->right != nullptr)
				level[next].push(tmp->right);
			//保存左子树
			if (tmp->left != nullptr)
				level[next].push(tmp->left);
		}
		//如果当前层打印完毕
		if (!level[current].empty())
		{
			cout << endl;
			current = 1 - current;
			next = 1 - next;
		}
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值