数据结构与算法实验3——栈和队列

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

设某银行有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<stdio.h>
int main()
{
    int n,m,i;
    int a[10086],b[10086],c[10086];
    int ji=0,ou=0,x=0,y=0,index=0;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%d",&m);
        if(m%2!=0)
        {
            a[ji++]=m;
        }
        else
        {
            b[ou++]=m;
        }
    }
    while(x<ji||y<ou)
    {
        if(x<ji)
        {
            c[index++]=a[x];
        }
        if(x+1<ji)
        {
            c[index++]=a[x+1];
        }
        x=x+2;
        if(y<ou)
        {
            c[index++]=b[y];
        }
        y=y+1;
    }
    for(i=0;i<index;i++)
    {
        if(i==0)
            printf("%d",c[i]);
        else
            printf(" %d",c[i]);
    }
    return 0;
}

7-2 表达式转换

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。

输入格式:

输入在一行中给出不含空格的中缀表达式,可包含+-*/以及左右括号(),表达式不超过20个字符。

输出格式:

在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。

输入样例:

2+3*(7-4)+8/4

输出样例:

2 3 7 4 - * + 8 4 / +
#include<stdio.h>
#include<string.h>
void print()
{
    static int flag=0;
    if(flag!=0)
        putchar(' ');
    flag++;
}
int main()
{
    char stack[10086];
    char str[10086];
    int top=-1,i;
    gets(str);
    int len=strlen(str);
    for(i=0;i<len;i++)
    {
        if((str[i]=='+'||str[i]=='-')&&(i==0||str[i-1]=='(')||isdigit(str[i]))
        {
            print();
            if(str[i]!='+')
                putchar(str[i]);
            while(str[i+1]=='.'||isdigit(str[i+1]))
                putchar(str[++i]);
        }
        else
        {
            if(str[i]==')')
            {
                while(top!=-1&&stack[top]!='(')
                {
                    print();
                    putchar(stack[top--]);
                }
                if(top!=-1)
                {
                    top--;
                }
            }
            else
            {
                if(top==-1)
                {
                    stack[++top]=str[i];
                }
                else
                {
                    while(top>-1&&stack[top]!='(')
                    {
                        if(str[i]=='('||((str[i]=='*'||str[i]=='/')&&(stack[top]=='+'||stack[top]=='-')))
                        {
                            break;
                        }
                        print();
                        putchar(stack[top--]);
                    }
                    stack[++top]=str[i];
                }
            }
        }
    }
    while(top>-1)
    {
        if(stack[top]=='(')
            top--;
        else
            print();
            putchar(stack[top--]);
    }
    return 0;
}

7-3 堆栈模拟队列

设已知有两个堆栈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<stdio.h>
int main()
{
    int n1,n2,x;
    int max,min;
    char c;
    scanf("%d %d",&n1,&n2);
    if(n1>n2)
    {
        max=n1;
        min=n2;
    }
    else
    {
        min=n1;
        max=n2;
    }
    int s1[min],s2[max];
    int top1=0,top2=0;
    getchar();
    while(scanf("%c",&c)&&c!='T')
    {
        if(c=='A')
        {
            scanf("%d",&x);
            if(top1<min)
                s1[top1++]=x;
            else
            {
                if(top2==0)
                {
                    while(top1!=0)
                    {
                        s2[top2++]=s1[--top1];
                    }
                    s1[top1++]=x;
                }
                else
                {
                    printf("ERROR:Full\n");
                }
            }
        }
        if(c=='D')
        {
            if(top2!=0)
            {
                printf("%d\n",s2[--top2]);
            }
            else
            {
                if(top1!=0)
                {
                    while(top1!=0)
                    {
                        s2[top2++]=s1[--top1];
                    }
                    printf("%d\n",s2[--top2]);
                }
                else
                    printf("ERROR:Empty\n");
            }
        }
    }
    return 0;
}

 7-4 输出全排列

请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间。

输入格式:

输入给出正整数n(<10)。

输出格式:

输出1到n的全排列。每种排列占一行,数字间无空格。排列的输出顺序为字典序,即序列a1​,a2​,⋯,an​排在序列b1​,b2​,⋯,bn​之前,如果存在k使得a1​=b1​,⋯,ak​=bk​ 并且 ak+1​<bk+1​。

输入样例:

3

输出样例:

123
132
213
231
312
321
 #include<stdio.h>
int a[10086],b[10086];
void quanpai(int n,int len)
{
    if(n==len)
    {
        for(int i=1;i<=n;i++)
        {
            printf("%d",a[i]);
        }
        printf("\n");
    }
    else
    {
        for(int k=1;k<=n;k++)
        {
            if(b[k]==0)
            {
                a[len+1]=k;
                b[k]=1;
                quanpai(n,len+1);
                b[k]=0;
            }
        }
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    quanpai(n,0);
    return 0;
}

7-5 括号匹配

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

输入格式:

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

输出格式:

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

输入样例1:

sin(10+20)

输出样例1:

yes

输入样例2:

{[}]

输出样例2:

no
#include<stdio.h>
int top=-1;
char stack[10086];
void push(char x)
{
   stack[++top]=x ;
}
char pop()
{
    if(top==-1)
        return 0;
    else
        return stack[top--];
}
int peidui(char str[])
{
    int i=0;
    while(str[i]!='\0')
    {
        if(str[i]=='('||str[i]=='{'||str[i]=='[')
            push(str[i]);
        else if(str[i]==')'||str[i]=='}'||str[i]==']')
        {
            if(top==-1||str[i]-pop()>2)
                return 0;
        }
        i=i+1;
    }
    return(top==-1);
}
int main()
{
    char str[10086];
    fgets(str,sizeof(str),stdin);
    if(peidui(str))
        printf("yes");
    else
        printf("no");
    return 0;
}

7-6 出栈序列的合法性

给定一个最大容量为 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 main()
{
    int stack[10086];
    int b[10086];
    int m,n,k;
    int flag,top;
    scanf("%d %d %d",&m,&n,&k);
    while(k--)
    {
        int index1=1,index2=0;
        flag=1;
        top=-1;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&b[i]);
        }
        while(index2<n)
        {
            if(top!=-1&&stack[top]==b[index2])
            {
                top--;
                index2++;
            }
            else
            {
                stack[++top]=index1++;
                if(top>=m)
                {
                    flag=0;
                    break;
                }
            }
        }
        if(flag==0||top!=-1)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}

7-7 后缀式求值

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

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

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

输入格式:

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

输出格式:

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

输入样例:

3 5.4 2.2 * +

输出样例:

14.9
#include<stdio.h>
int main()
{
    char str[10086];
    double st[10086];
    int i;
    while(scanf("%s",str)!=EOF)
    {
        if(str[1]=='\0'&&(str[0]=='+'||str[0]=='-'||str[0]=='*'||str[0]=='/'))
        {
            double num1,num2,current;
            num1=st[--i];
            num2=st[--i];
            switch(str[0])
            {
                    case'+':current=num2+num1;st[i++]=current;break;
                    case'-':current=num2-num1;st[i++]=current;break;
                    case'*':current=num2*num1;st[i++]=current;break;
                    case'/':current=num2/num1;st[i++]=current;break;
            }
        }
        else
        {
            double num;
            sscanf(str,"%lf",&num);
            st[i++]=num;
        }
    }
    printf("%.1f",st[0]);
}

7-8 进制转换

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

输入格式:

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

输出格式:

输出对应的结果。

输入样例:

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

123 2

输出样例:

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

1111011
#include<stdio.h>
int main()
{
    int n,x,a,b;
    int i=1;
    scanf("%d %d",&n,&x);
    if(x==2)
    {
        while(n!=0)
        {
        a=n%2;
        n=n/2;
        b=b+i*a;
        i=i*10;
        }
        printf("%d",b);
    }
    else if(x==8)
    {
        printf("%o",n);
    }
    else if(x==16)
    {
        char str[10086];
        sprintf(str,"%X",n);
        printf("%s",str);
    }
    return 0;
}

7-9 行编辑器

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

输入格式:

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

输出格式:

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

输入样例1:

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

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

输出样例1:

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

while(*s)

输入样例2:

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

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

输出样例2:

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

putchar(*s++);
#include<stdio.h>
void bj(char input[])
{
    int index=0;
    char hc[10086];
    for(int i=0;input[i]!='\0';i++)
    {
        if(input[i]=='#')
        {
            if(index>0)
            {
                index--;
            }
        }
        else if(input[i]=='@')
            index=0;
        else
        {
            hc[index++]=input[i];
        }
    }
    hc[index]='\0';
    printf("%s",hc);
}
int main()
{
    char input[10086];
    fgets(input,sizeof(input),stdin);
    input[strcspn(input,"\n")]='\0';
    bj(input);
    return 0;
}

7-10 选数

已知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 sum,t=0;
int a[10086],b[10086];
int k;
void fun(int n,int m)
{
    int i;
    if(m==0)
    {
        sum=0;
        for(i=0;i<k;i++)
        {
            sum=sum+b[i];
        }
        if(sushu(sum))
        {
            t++;
        }
    }
    else
    {
        for(i=n;i>=m;i--)
        {
            b[m-1]=a[i];
            fun(i-1,m-1);
        }
    }
}
int sushu(int n)
{
    int i;
    if(n==2)
        return 1;
        for(i=2;i<=n-1;i++)
        {
            if(n%i==0)
                break;
        }
        if(i==n)
            return 1;
        else
            return 0;
}
int main()
{
    int i,n;
    scanf("%d %d",&n,&k);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    fun(n,k);
    printf("%d\n",t);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值