数据结构 堆栈

Posted 上山打老虎D

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构 堆栈相关的知识,希望对你有一定的参考价值。

1. DS堆栈–逆序输出(STL栈使用)

题目描述

C++中已经自带堆栈对象stack,无需编写堆栈操作的具体实现代码。

本题目主要帮助大家熟悉stack对象的使用,然后实现字符串的逆序输出

输入一个字符串,按字符按输入顺序压入堆栈,然后根据堆栈后进先出的特点,做逆序输出

stack类使用的参考代码

n包含头文件:#include

n创建一个堆栈对象s(注意stack是模板类):stack s;//堆栈的数据类型是字符型

n把一个字符ct压入堆栈:s.push(ct);

n把栈顶元素弹出:s.pop();

n获取栈顶元素,放入变量c2:c2 =s.top();

n判断堆栈是否空:s.empty(),如果为空则函数返回true,如果不空则返回false

输入

第一行输入t,表示有t个测试实例
第二起,每一行输入一个字符串,注意字符串不要包含空格

字符串的输入可以考虑一下代码:

#include

int main()

{ string str;

Int len;

cin>>str; //把输入的字符串保存在变量str中

len = str.length() //获取输入字符串的长度

}

输出

每行逆序输出每一个字符串

输入样例

2
abcdef
aabbcc

输出样例

fedcba
ccbbaa

参考代码

#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string str;
        int len;
        cin>>str;
        len = str.size();
        stack<char> s;
        for(int i=0;i<len;i++)
        {
            char ct=str[i];
            s.push(ct);
        }
        for(int i=0;i<len;i++)
        {
            str[i]=s.top();
            s.pop();
        }
        cout<<str<<endl;


    }
}

2. DS堆栈–行编辑

题目描述

使用C++的STL堆栈对象,编写程序实现行编辑功能。行编辑功能是:当输入#字符,则执行退格操作;如果无字符可退就不操作,不会报错

本程序默认不会显示#字符,所以连续输入多个#表示连续执行多次退格操作

每输入一行字符打回车则表示字符串结束

注意:必须使用堆栈实现,而且结果必须是正序输出

输入

第一行输入一个整数t,表示有t行字符串要输入
第二行起输入一行字符串,共输入t行

输出

每行输出最终处理后的结果,如果一行输入的字符串经过处理后没有字符输出,则直接输出NULL

输入样例

4
chinaa#
sb#zb#u
##shen###zhen###
chi##a#####

输出样例

china
szu
sz
NULL

参考代码

#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string str;
        int len;
        cin>>str;
        len = str.size();
        stack<char> s;
        for(int i = 0;i<len;i++)
        {
            if(str[i] == '#')
            {
                if(!s.empty())
                    s.pop();
            }
            else
            {
                s.push(str[i]);
                //cout<<str[i];
            }
        }
        if(s.empty())
        {
            cout<<"NULL"<<endl;
            continue;
        }
        str.clear();
        len=0;
        while(!s.empty())
        {
            str+=s.top();
            len++;
            s.pop();
        }
        //cout<<len<<endl;
        for(int i=0;i<len;i++)
        {
            char ct=str[i];
            s.push(ct);
        }
        for(int i=0;i<len;i++)
        {
            str[i]=s.top();
            s.pop();
        }
        cout<<str<<endl;


    }
}

3. DS堆栈–括号匹配

题目描述

处理表达式过程中需要对括号匹配进行检验,括号匹配包括三种:“(”和“)”,“[”和“]”,“{”和“}”。例如表达式中包含括号如下:

()[()([])]{}
123456789101112

从上例可以看出第1和第2个括号匹配,第3和第10个括号匹配,4和5匹配,6和9匹配,7和8匹配,11和12匹配。从中可以看到括号嵌套的的情况是比较复杂的,使用堆栈可以很方便的处理这种括号匹配检验,可以遵循以下规则:

1、 当接收第1个左括号,表示新的一组匹配检查开始;随后如果连续接收到左括号,则不断进堆栈。

2、 当接受第1个右括号,则和最新进栈的左括号进行匹配,表示嵌套中1组括号已经匹配消除

3、 若到最后,括号不能完全匹配,则说明输入的表达式有错

建议使用C++自带的stack对象来实现

stack类使用的参考代码

n包含头文件:#include

n创建一个堆栈对象s(注意stack是模板类):stack s;//堆栈的数据类型是字符型

n把一个字符ct压入堆栈:s.push(ct);

n把栈顶元素弹出:s.pop();

n获取栈顶元素,放入变量c2:c2 =s.top();

n判断堆栈是否空:s.empty(),如果为空则函数返回true,如果不空则返回false

输入

第一行输入一个t,表示下面将有t组测试数据。接下来的t行的每行输入一个表达式,表达式只考虑英文半角状态输入,无需考虑中文全角输入

输出

对于每一行的表达式,检查括号是否匹配,匹配则输入ok,不匹配则输出error

输入样例

2
(a+b)[45+(-6)]
[5
8]/{(a+b)-6

输出样例

ok
error

参考代码

#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        stack<char> s;
        string str;
        cin>>str;
        for(int i=0;i<str.size();i++)
        {
            if(str[i]=='('||str[i]=='{'||str[i]=='[')
                s.push(str[i]);
            else
            {
                if(str[i]==')')
                {
                    if(s.top()=='(')
                        s.pop();
                }
                else if(str[i]=='}')
                {
                    if(s.top()=='{')
                        s.pop();
                }
                else if(str[i]==']')
                {
                    if(s.top()=='[')
                        s.pop();
                }
            }

        }
        if(s.empty())
            cout<<"ok"<<endl;
        else
            cout<<"error"<<endl;
    }
}

4. DS堆栈–迷宫求解

题目描述

给出一个N*N的迷宫矩阵示意图,从起点[0,0]出发,寻找路径到达终点[N-1, N-1]

要求使用堆栈对象来实现,具体算法参考课本3.2.4节51页

输入

第一行输入t,表示有t个迷宫

第二行输入n,表示第一个迷宫有n行n列

第三行起,输入迷宫每一行的每个方格的状态,0表示可通过,1表示不可通过

输入n行

以此类推输入下一个迷宫

输出

逐个输出迷宫的路径

如果迷宫不存在路径,则输出no path并回车

如果迷宫存在路径,将路径中每个方格的x和y坐标输出,从起点到终点,每输出四个方格就换行,最终以单词END结尾,具体格式参考示范数据

输出的代码参考如下:

//path是保存路径的堆栈,堆栈中每个元素都包含x坐标和y坐标,用属性xp和yp表示

//path1是一个临时堆栈,把path的数据倒序输出到path1,使得路径按正序输出

if (!path.empty())//找到路径

{//…若干代码,实现path的数据导入path1

i=0; //以下是输出路径的代码

while (!path1.empty())

{cpos = path1.top();

if ( (++i)%4 == 0 )

cout<<’[’<<cpos.xp<<’,’<<cpos.yp<<’]’<<"–"<<endl;

else

cout<<’[’<<cpos.xp<<’,’<<cpos.yp<<’]’<<"–";

path1.pop();

}

cout<<“END”<<endl;

}

else

cout<<“no path”<<endl; //找不到路径输出no path

输入样例

2
8
0 0 0 1 1 1 1 1
1 0 0 0 1 0 0 1
1 0 0 0 1 0 0 0
1 1 0 0 0 0 0 1
0 0 1 1 0 1 1 0
0 0 0 0 0 0 1 1
1 1 1 1 1 0 0 1
0 0 0 0 1 0 0 0
7
0 0 0 1 1 1 1
1 0 0 1 0 0 1
1 0 0 1 0 0 0
1 1 0 0 0 0 1
0 0 1 1 0 1 0
1 0 0 0 0 1 0
0 0 0 0 1 1 0

输出样例

[0,0]–[0,1]–[0,2]–[1,2]–
[1,3]–[2,3]–[3,3]–[3,4]–
[4,4]–[5,4]–[5,5]–[6,5]–
[6,6]–[7,6]–[7,7]–END
no path

参考代码

#include<iostream>
#include<stack>
#include<string>
using namespace std;
class pos
{
public:
    int xp,yp;
    int p;
    int dir;
    void set(int a,int b,int c)
    {
        xp=a,yp=b,p=c;
    }
};

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        stack<pos> s;
        pos a[n+2][n+2];
        pos b,temp;
        for(int i=0;i<n+2;i++)
            for(int j=0;j<n+2;j++)
                a[i][j].set(i,j,1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                int k;
                cin>>k;
                a[i][j].set(i,j,k);
            }
        s.push(a[1][1]);
        int x=1,y=1;
        while(!s.empty())
        {
            b=s.top();
            s.pop();
            if(s.empty())
                temp=b;
            else
                temp=s.top();
            s.push(b);
            if(x==n&&y==n)
            {
                break;
            }
            if(a[x+1][y].p==0&&x+1!=temp.xp)
            {
                x++;
                a[x][y].p=1;
                s.push(a[x][y]);
            }
            else if(a[x][y+1].p==0&&y+1!=temp.yp)
            {
                y++;
                a[x][y].p=1;
                s.push(a[x][y]);
            }
            else if(a[x-1][y].p==0&&x-1!=temp.xp)
            {
                x--;
                a[x][y].p=1;
                s.push(a[x][y]);
            }
            else if(a[x][y-1].p==0&&y-1!=temp.yp)
            {
                y--;
                a[x][y].p=1;
                s.push(a[x][y]);

            }
            else
            {
                a[x][y].p=1;
                s.pop();
            }

        }
        if(!s.empty())
        {
            stack<pos> ans;
            while(!s.empty())
            {
                ans.push(s.top());
                s.pop();
            }
            int ii=0;
            while(!ans.empty())
            {
                temp=ans.top();
                cout<<'['<<temp.xp-1<<','<<temp.yp-1<<']'<<"--";
                if((++ii)%4==0)
                    cout<<endl;
                ans.pop();
            }
            cout<<"END"<<endl;
        }
        else
        {
            cout<<"no path"<<endl;
        }
    }
}

5. DS堆栈–表达式计算

题目描述

计算一个表达式的运算结果

使用C++自带stack堆栈对象来实现

参考课本的算法伪代码P53-54

例如

  1. Push (OPTR, ‘#’);表示把字符#压入堆栈OPTR中,转换成c++代码就是OPTR.push(’#’);

  2. Pop(OPND, a); 表示弹出栈OPND的栈顶元素,并把栈顶元素放入变量a中。因此改成c++代码是两个操作:
    a = OPND.top();
    OPND.pop();

  3. a = GetTop(OPND)表示获取栈OPND的栈顶元素,转成c++代码就是: a = OPND.top();



输入

第一个输入t,表示有t个实例

第二行起,每行输入一个表达式,每个表达式末尾带#表示结束

输入t行

输出

每行输出一个表达式的计算结果,计算结果用浮点数(含4位小数)的格式表示

用cout控制浮点数输出的小数位数,需要增加一个库文件,并使用fixed和setprecision函数,代码如下:

#include
#include
using namespace std;

int main()

{ double temp = 12.34

cout<<fixed<<setprecision(4)<<temp<<endl;

}

输出结果为12.3400

输入样例

2
1+2*3-4/5#
(66+(((11+22)*2-33)/3+6)*2)-45.6789#

输出样例

6.2000
54.3211

参考代码

#include <iostream>
#include <stack>
#include <string>
#include <cstdlib>
#include <iomanip>
#include <cstring>
using namespace std;
#define ok 0
#define error -1
#define overflow -1
#define opsetsize 7
typedef int Status;
char Prior[7][7] = {
	'>',
	'>',
	'<',
	'<',
	'<',
	'>',
	'>',
	'>',
	'>',
	'<',
	'<',
	'<',
	'>',
	'>',
	'>',
	'>',
	'>',
	'>',
	'<',
	'>',
	'>',
	'>',
	'>',
	'>',
	'>',
	'<',
	'>',
	'>',
	'<',
	'<',
	'<',
	'<',
	'<',
	'=',
	' ',
	'>',
	'>',
	'>',
	'>',
	' ',
	'>',
	'>',
	'<',
	'<',
	'<',
	'<',
	'<',
	' ',
	'=',
};
float Operate(float a, unsigned char theta, float b)
{
	if (theta == '+')
		return a + b;
	else if (theta == '-')
		return a - b;
	else if (theta == '*')
		return a * b;
	else if (theta == '/')
		return a / b;
}
char OPSET[opsetsize] = {'+', '-', '*', '/', '(', ')', '#'};
Status In(char Test, char *TestOp)
{
	for (int i = 0; i < opsetsize在后台堆栈中多次防止相同的片段

从后台堆栈恢复片段时的 savedInstanceState

将新片段添加到后台堆栈是不是会暂停当前片段?

从堆栈中弹出特定片段并删除其他片段

Android TalkBack 和片段堆栈

来自后台堆栈的片段 onResume