PTA——21级数据结构与算法实验3——栈和队列(参考答案)

7-1 进制转换

输入十进制整数N和待转换的进制x(2、8、16),分别代表十进制N转换成二进制、八进制和十六进制,输出对应的结果。十六进制中A~F用大写字母表示。

输入格式:

输入两个整数N(十进制整数N)和x(x进制),中间用空格隔开。

输出格式:

输出对应的结果。

输入样例:

在这里给出一组输入。例如:

123 2

输出样例:

在这里给出相应的输出。例如:

1111011

输入样例:

在这里给出一组输入。例如:

123 16

输出样例:

在这里给出相应的输出。例如:

7B
#include<iostream>

#include<stdio.h>

using namespace std;

int main(){

    int n,x;

    cin>>n>>x;

    int b,i=1,j=0;

    if(x==2){

        while(n!=0){

            b=n%2;

            n/=2;

            j+=i*b;

            i*=10;

        }

        cout<<j<<endl;

    }

    if(x==8)

        cout<<oct<<n<<endl;

    if(x==16){

        char s[10000];

        sprintf(s,"%X",n);

        cout<<s<<endl;

    }

    return 0;

}

7-2 中缀表达式转换为后缀表达式

所谓中缀表达式,指的是运算符处于操作数的中间(例:3 * ( 4 + 2 )),中缀表达式是人们常用的算术表示方法,但中缀表达式不容易被计算机解析,因为既要考虑运算符的优先级,还要考虑括号的处理。但中缀表达式仍被许多程序语言使用,因为它符合人们的普遍用法。后缀表达式,指的是不包含括号,运算符放在两个操作数的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,也不需要考虑括号)。

给出一个中缀表达式,请将其转换为后缀表达式并输出。

输入格式:

只有一行,是一个长度不超过1000的字符串,表示一个中缀表达式。表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。运算符、操作数之间用一个空格分隔,数据保证输入的操作数中不会出现负数,保证除数不会为0。

输出格式:

输出对应的后缀表达式。运算符、操作数之间用一个空格分隔,但行尾无多余空格。

输入样例:

3 * ( 4 + 2 )

输出样例:

3 4 2 + *
#include<stdio.h>
#include<string.h>
int main(){
	char a[1000],s[20];
	gets(a);
	int len=strlen(a),k=0,en=-1;
	for(int i=0;i<len;i++){
		if(a[i]>='0'&&a[i]<='9'||a[i]=='.'){
			if(k)printf(" ");
			k=1;
			while(a[i]>='0'&&a[i]<='9'||a[i]=='.'){
				printf("%c",a[i++]);
			}
			i--;
		}
		else{
			if(a[i]=='(')s[++en]=a[i];
			else if(a[i]=='*'||a[i]=='/'){
				while(s[en]=='*'||s[en]=='/'&&en!=-1){
					printf(" %c",s[en--]);
				}
				s[++en]=a[i];
			}
			else if(a[i]==')'){
				while(s[en]!='('){
					printf(" %c",s[en--]);
				}
				en--;
			}
			else if(a[i]=='+'||a[i]=='-'){
				while(s[en]!='('&&en!=-1){
					printf(" %c",s[en--]);
				}
				s[++en]=a[i];
			}
		}
	}
	while(en!=-1){
		printf(" %c",s[en--]);
	}
	return 0;
}

7-3 后缀式求值

我们人类习惯于书写“中缀式”,如 3 + 5 * 2 ,其值为13。 (p.s. 为什么人类习惯中缀式呢?是因为中缀式比后缀式好用么?)

而计算机更加习惯“后缀式”(也叫“逆波兰式”,Reverse Polish Notation)。上述中缀式对应的后缀式是: 3 5 2 * +

现在,请对输入的后缀式进行求值。

输入格式:

在一行中输入一个后缀式,运算数运算符之间用空格分隔,运算数长度不超过6位,运算符仅有+ - * / 四种。

输出格式:

在一行中输出后缀式的值,保留一位小数。

输入样例:

3 5.4 2.2 * +

输出样例:

14.9
#include "iostream"

#include "sstream"

#include "vector"

#include "iomanip"

using namespace std;



/**

 * 做运算

 * @param temp1 double类型的temp1

 * @param temp2 double类型的temp2

 * @param temp string类型的temp

 * @return 返回运算结果

 */

double calculate(double temp1, double temp2, string temp) {

    if (temp == "+")return temp1+temp2;

    if (temp == "-")return temp1-temp2;

    if (temp == "*")return temp1*temp2;

    if (temp == "/")return temp1/temp2;

}



int main(){

    string str;

    //用stk模拟一个栈

    vector<double>stk;

    //读取题目中输入的数据(整行读取)

    getline(cin,str);



    //使用for循环对上面str字符串中的每一个字符做遍历

    for(int i=0;i<str.size();i++){

        string temp;

        while (str[i]!=' ' && i<str.size()){

            //如果没有读到空格,则读到空格为止,并将读到的数据给temp

            temp.push_back(str[i]);

            i++;

        }



        //如果读到空格了,就判断空格前的内容是数字还是运算符

        if(temp!="+" && temp!="-" && temp!="*" && temp!="/"){

            //如果temp不是运算符,则一定是数字,用stringstream将

            //string类型的temp转成double类型

            stringstream st;

            double temp1;

            st<<temp;

            st>>temp1;

            //将得到的数字压入到栈中,以便后续计算

            stk.push_back(temp1);

        } else {

            //如果temp是运算符,则将栈顶和 栈顶-1 个数据取出

            //与对应的运算符做运算

            //注意:读到运算符时,栈中至少有2个数字数据,否则所给表达式本来就是错的

            double temp1 = stk.back();

            stk.pop_back();

            double temp2 = stk.back();

            stk.pop_back();

            //做计算,把计算结果给temp3

            double temp3 = calculate(temp2,temp1,temp);

            stk.push_back(temp3);

        }

    }

    

    //所有计算完成后,栈中唯一的数据就是答案啦

    cout<<fixed<<setprecision(1)<<stk.back();

}

7-4 括号匹配

给定一串字符,不超过100个字符,可能包括括号、数字、字母、标点符号、空格,编程检查这一串字符中的( ) ,[ ],{ }是否匹配。

输入格式:

输入在一行中给出一行字符串,不超过100个字符,可能包括括号、数字、字母、标点符号、空格。

输出格式:

如果括号配对,输出yes,否则输出no。

输入样例1:

sin(10+20)

输出样例1:

yes

输入样例2:

{[}]

输出样例2:

no
#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

typedef char ElementType;

typedef struct Node *PtrToNode;

struct Node {

    ElementType Data;

    PtrToNode   Next;

};

typedef PtrToNode List;



List Create();

bool isEmpty(List L);//栈是否为空

bool Push(List L, ElementType x);

ElementType Pop(List L);

bool isTrue(char s[]);//括号匹配

int main()

{

    char s[101];

    gets(s);

    if(isTrue(s)){

        printf("yes\n");

    }else{

        printf("no\n");

    }

}

List Create()

{

    List L = (List)malloc(sizeof(struct Node));

    L->Next = NULL;

    return L;

}



bool isEmpty(List L)

{

    return (L->Next == NULL);

}



bool Push(List L, ElementType x)

{

    bool flag = false;

    List p = (List)malloc(sizeof(struct Node));

    p->Data = x;

    p->Next = L->Next;

    L->Next = p;

    flag = true;

    return flag;

}



ElementType Pop(List L)

{

    if(isEmpty(L))

    {

        return '-1';

    }

    else

    {

        ElementType flag = L->Next->Data;

        List p;

        p = L->Next;

        L->Next = p->Next;

        free(p);

        return flag;

    }

}

bool isTrue(char s[]){

    int i=0;

    char x;

    bool flag=true;

    List L=Create();

    while(s[i]!='\0'){

        if(s[i]=='('||s[i]=='['||s[i]=='{'){

            Push(L,s[i]);

        }

        if(s[i]==')'){

            x=Pop(L);

            if(x!='('){

                flag=false;

                break;

            }

        }

        if(s[i]==']'){

            x=Pop(L);

            if(x!='['){

                flag=false;

                break;

            }

        }

        if(s[i]=='}'){

            x=Pop(L);

            if(x!='{'){

                flag=false;

                break;

            }

        }

        i++;

    }

    if(!isEmpty(L))

        flag=false;

    return flag;

}

7-5 出栈序列的合法性

给定一个最大容量为 M 的堆栈,将 N 个数字按 1, 2, 3, ..., N 的顺序入栈,允许按任何顺序出栈,则哪些数字序列是不可能得到的?例如给定 M=5、N=7,则我们有可能得到{ 1, 2, 3, 4, 5, 6, 7 },但不可能得到{ 3, 2, 1, 7, 5, 6, 4 }。

输入格式:

输入第一行给出 3 个不超过 1000 的正整数:M(堆栈最大容量)、N(入栈元素个数)、K(待检查的出栈序列个数)。最后 K 行,每行给出 N 个数字的出栈序列。所有同行数字以空格间隔。

输出格式:

对每一行出栈序列,如果其的确是有可能得到的合法序列,就在一行中输出YES,否则输出NO

输入样例:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

输出样例:

YES
NO
NO
YES
NO
#include<stdio.h>

int m,n,k;

int stack[1007];       //栈

int top=0;             //栈顶下标

int index1=1,index2=1;     //index1来表示1-n的数字 ,index2来表示数组b的下标

int b[1007];           //存放出栈序列



int main()

{

    scanf("%d%d%d",&m,&n,&k);

    while(k--)

    {

     int flag=1;

     index1=1;index2=1;

     top=0;

     int i;

     for(i=1;i<=n;i++)

       scanf("%d",&b[i]);

     while(1)

     {

     //判断给出的出栈序列如果和1到n增长顺序相同,那就是入栈一个元素,然后立即出栈。

     if(index1==b[index2])

     {

     index1++;

     index2++;

}

//判断如果栈中有元素,然后栈顶元素也与此时的出栈序列元素相同,那么就继续出栈来判断

else if(top!=0&&stack[top-1]==b[index2])

{

top--;

index2++;

}

else

{

if(index1>n)break;  //已经判断结束,就跳出循环

stack[top]=index1;  //元素入栈

top++;

index1++;

if(top>=m) //

{

flag=0;

break;

}

}

}

if(flag==0||top!=0)printf("NO\n");

else printf("YES\n");

}

    

return 0;

}

7-6 行编辑器

一个简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,并存入用户的数据区。
由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区”的做法显然不是最恰当的。较好的做法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。允许用户输入出差错,并在发现有误时可以及时更正。例如,当用户发现刚刚键入的一个字符是错的时,可补进一个退格符"#",以表示前一个字符无效;
如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符"@",以表示当前行中的字符均无效。
如果已经在行首继续输入'#'符号无效。

输入格式:

输入一个多行的字符序列。但行字符总数(包含退格符和退行符)不大于250。

输出格式:

按照上述说明得到的输出。

输入样例1:

在这里给出一组输入。例如:

whli##ilr#e(s#*s)

输出样例1:

在这里给出相应的输出。例如:

while(*s)

输入样例2:

在这里给出一组输入。例如:

outcha@putchar(*s=#++);

输出样例2:

在这里给出相应的输出。例如:

putchar(*s++);
#include<iostream>

using namespace std;

int main(){

    string s;

    while(getline(cin,s)){

        int k=0;

        char a[80];

        for(int i=0;i<s.size();i++){

            if(s[i]=='#'&&k==0)continue;

            else if(s[i]=='#')k--;

            else if(s[i]=='@')k=0;

            else a[k++]=s[i];

        }

        for(int i=0;i<k;i++)cout<<a[i];

        cout<<endl;

    }

    return 0;

}

7-7 银行业务队列简单模拟

设某银行有A、B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 —— 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客。给定到达银行的顾客序列,请按业务完成的顺序输出顾客序列。假定不考虑顾客先后到达的时间间隔,并且当不同窗口同时处理完2个顾客时,A窗口顾客优先输出。

输入格式:

输入为一行正整数,其中第1个数字N(≤1000)为顾客总数,后面跟着N位顾客的编号。编号为奇数的顾客需要到A窗口办理业务,为偶数的顾客则去B窗口。数字间以空格分隔。

输出格式:

按业务处理完成的顺序输出顾客的编号。数字间以空格分隔,但最后一个编号后不能有多余的空格。

输入样例:

8 2 1 3 9 4 11 13 15

输出样例:

1 3 2 9 11 4 13 15
#include <iostream>

#include <stdlib.h>

#include <queue>

#include <vector>

using namespace std;

int main()

{

    queue<int> A,B;

    int N,flag1=0,flag2=0;

    cin>>N;

    int number[N];

    vector<int> storeA;

    vector<int> storeB;

    vector<int> storeC;

    for(int i = 0; i<N; i++)

    {

        cin>>number[i];

    }

    for(int i = 0; i<N; i++)

    {

        if(number[i]%2!=0)

        {

            A.push(number[i]);

            storeA.push_back(number[i]);

        }

        else

        {

            B.push(number[i]);

            storeB.push_back(number[i]);

        }

    }

    while(!A.empty()||!B.empty())

    {

        if(!A.empty())

        {

            storeC.push_back(storeA.at(flag1));

            A.pop();

            flag1++;

        }

        if(!A.empty())

        {

            storeC.push_back(storeA.at(flag1));

            A.pop();

            flag1++;

        }

        if(!B.empty())

        {

            storeC.push_back(storeB.at(flag2));

            B.pop();

            flag2++;

        }

    }

    vector<int>::iterator t=storeC.begin();

    for(t; t!=storeC.end()-1; t++)

    {

        cout<<*t<<" ";

    }

    cout<<*t;

    return 0;

}

7-8 堆栈模拟队列

设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q。

所谓用堆栈模拟队列,实际上就是通过调用堆栈的下列操作函数:

  • int IsFull(Stack S):判断堆栈S是否已满,返回1或0;
  • int IsEmpty (Stack S ):判断堆栈S是否为空,返回1或0;
  • void Push(Stack S, ElementType item ):将元素item压入堆栈S
  • ElementType Pop(Stack S ):删除并返回S的栈顶元素。

实现队列的操作,即入队void AddQ(ElementType item)和出队ElementType DeleteQ()

输入格式:

输入首先给出两个正整数N1N2,表示堆栈S1S2的最大容量。随后给出一系列的队列操作:A item表示将item入列(这里假设item为整型数字);D表示出队操作;T表示输入结束。

输出格式:

对输入中的每个D操作,输出相应出队的数字,或者错误信息ERROR:Empty。如果入队操作无法执行,也需要输出ERROR:Full。每个输出占1行。

输入样例:

3 2
A 1 A 2 A 3 A 4 A 5 D A 6 D A 7 D A 8 D D D D T

输出样例:

ERROR:Full
1
ERROR:Full
2
3
4
7
8
ERROR:Empty
#include<bits/stdc++.h>

#define ll long long

#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

using namespace std;

const ll MAXN = 1e12 + 10;

ll n, m, i, j, k, t, w, x, y, z, in, flag, cou, sum, maxn, minn;

string s, s1, s2;

const ll INF = 1e9 + 7;



int main()

{

    FAST_IO;

    cin >> n >> m;



    if ( n > m ) swap ( n, m );



    stack<ll>st1, st2;



    while ( cin >> s && s != "T" )

    {

        if ( s == "A" )

        {

            cin >> t;

            if ( st1.size() < n ) st1.push ( t );

            else if ( st2.empty() )

            {

                while ( !st1.empty() ) st2.push ( st1.top() ), st1.pop();

                st1.push(t);

            }

            else cout << "ERROR:Full" << endl;

        }

        else

        {

            if ( !st2.empty() ) cout << st2.top() << endl, st2.pop();

            else if ( !st1.empty() )

            {

                while ( !st1.empty() ) st2.push ( st1.top() ), st1.pop();



                cout << st2.top() << endl, st2.pop();



                while ( !st2.empty() ) st1.push ( st2.top() ), st2.pop();

            }

            else cout << "ERROR:Empty" << endl;

        }

    }



    return 0;

}

7-9 选数

已知n个整数x1,x2,x3...xi,以及1个整数k(k<n)。从 n 个整数中任选 k个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4个整数分别为3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22,
3+7+19=29,
7+12+19=38,
3+12+19=34,

现在,要求你计算出和为素数共有多少种。

例如上例,只有一种的和为素数:3+7+19=29

输入格式:

第一行两个空格隔开的整数 n,k(1≤n≤20,k<n)
第二行n个整数,两数之间空格隔开(1≤xi≤1000000)

输出格式:

输出一个整数,表示种类数。

输入样例:

在这里给出一组输入。例如:

4 3
3 7 12 19

输出样例:

在这里给出相应的输出。例如:

1
#include <stdio.h>

int sushu(int n);

void fun(int n, int m);

int a[22], b[21], n, k, t = 0;

int main()

{

    int i;

    scanf("%d%d", &n, &k);

    int b[k];

    for(i = 1; i <= n; i++)

        scanf("%d", &a[i]);

    fun(n, k);

    printf("%d", t);

}



void fun(int n, int m)//从n里面选m个数字

{

    int i, sum;

    if(m == 0)

    {

        sum = 0;

        for(i = 0; i < k; i++)

            sum += b[i];

        if(sushu(sum))

            t++;

        return;

    }

    for(i = n ; i >= m; i--)

    {

        b[m - 1] = a[i];

        fun(i - 1, m - 1);

    }

}



int sushu(int n)

{

    int i;

    for(i = 2; i < n; i++)

        if(n % i == 0)

            break;

    if(i == n || n == 2)

        return 1;

    else

        return 0;

}

7-11 全排列

Lc今天上课学会了数的全排列并且Lc觉得数的全排列很简单,但是直到Lc的同桌YooQ向他提出了一个问题,该问题的描述如下:我们知道n的全排列总共有n!个序列,例如2的全排列有两个序列{1,2}和{2,1},现在你要解决的问题是n的全排列的n!个序列中第m个序列是什么?(注意:n的全排列的n!个序列是按字典序由小到大排序的)

输入格式:

第一行为样例组数t(t≤1e5),接下来t行每行有一个整数n和m(1<=n<=20,1<=m<=n!)

输出格式:

输出t行,每行输出n的全排列的n!个序列中第m个序列,两相邻的数间有一空格,行末不得有多余空格。

输入样例:

在这里给出一组输入。例如:

2
1 1
3 6

输出样例:

在这里给出相应的输出。例如:

1
3 2 1
#include<iostream>

#include<algorithm>

using namespace std;

int s[1000000];

int main()

{

    int n,m;

    int T;

    scanf("%d",&T);

    while(T--){

    scanf("%d%d",&n,&m);

    {

        int i;

        for(i=0;i<n;i++)

        {

            s[i]=i+1;

        }

        int t=2;

        while(next_permutation(s,s+n))

        {

               if(t==m)

            {

               for(int i=0;i<n-1;i++)

                 {

                      cout<<s[i]<<" ";

                }

                    cout<<s[n-1]<<endl;

                    break;

            }

            t++;

        }

        if(m==1)

            {

                for(int i=0;i<n-1;i++)

                 cout<<s[i]<<" ";

                 cout<<s[n-1]<<endl;

            }

    }

    }

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

救救孩子√

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值