双栈的基本操作
描述
将编号为0和1的两个栈存放于一个数组空间V[m]中,栈底分别处于数组的两端。当第0号栈的栈顶指针top[0]等于-1时该栈为空;当第1号栈的栈顶指针top[1]等于m时,该栈为空。两个栈均从两端向中间增长(见下图)。试编写双栈初始化,判断栈空、栈满、进栈和出栈算法的函数。函数调用次序依次为:进栈、栈满的判断、出栈、栈空的判断。
双栈数据结构的定义如下:
typedef struct
{
int top[2], bot[2]; //栈顶和栈底指针
SElemType *V; //栈数组
int m; //栈最大可容纳元素个数
}DblStack;
双栈结构的表示
输入
多组数据,每组数据有四行,每行的数据之间均用空格分隔。第一行为一个整数m,表示数组V的大小,第二行为四个整数e0、e1、d0、d1,e0和e1分别代表压入0号栈和1号栈的整数序列E0和E1的长度(依次连续入栈,中间没有出栈的情况),d0和d1分别代表从0号栈和1号栈弹出的序列的长度(依次连续出栈,中间没有入栈的情况)。第三行和第四行分别表示序列E0和E1。当m=0时,输入结束。
输出
对于每组数据输出三行。第一行代表进栈操作完成时栈是否为满(出栈操作尚未执行),栈满输出1,栈不满输出0。第二行和第三行的数据分别对应0号栈和1号栈。第二行包括d0+1个整数,其中前d0个整数代表出栈序列D0,最后一个整数代表出栈操作完成时0号栈是否为空,栈空输出0,不空输出1。第三行包括d1+1个整数,其中前d1个整数代表出栈序列D1,最后一个整数代表出栈操作完成时1号栈是否为空,栈空输出0,不空输出1。整数之间用空格分隔。
输入样例 1
7 3 4 2 2 1 2 3 2 3 4 5 12 4 6 4 3 1 3 4 5 1 3 5 6 8 1 0输出样例 1
1 3 2 1 5 4 1 0 5 4 3 1 0 1 8 6 1#include<bits/stdc++.h> using namespace std; typedef struct { int top[2],bot[2]; int *V; int m; }DStack; int InitStack(DStack &s,int m) { s.V=new int[m]; s.top[0]=s.bot[0]=-1; s.top[1]=s.bot[1]=m; } int isEmpty(DStack s,int i) { if(s.top[i]==s.bot[i]) return 0; else return 1; } int isFull(DStack s) { if(s.top[0]+1==s.top[1]) return 1; else return 0; } int Push(DStack &s,int i,int x) { if(s.top[0]+1==s.top[1]) return 0; if(i==0) { s.top[0]++; s.V[s.top[0]]=x; } else { s.top[1]--; s.V[s.top[1]]=x; } return 1; } int Pop(DStack &s,int i,int &x) { if(s.top[i]==s.bot[i]) return 0; if(i==0) { x=s.V[s.top[0]]; s.top[0]--; } else { x=s.V[s.top[1]]; s.top[1]++; } return 1; } int main() { int n; while(cin>>n&&n!=0) { DStack s; InitStack(s,n); int a,b,c,d; cin>>a>>b>>c>>d; int x; for(int i=0;i<a;i++) { cin>>x; Push(s,0,x); } for(int i=0;i<b;i++) { cin>>x; Push(s,1,x); } cout<<isFull(s)<<endl; for(int i=0;i<c;i++) { Pop(s,0,x); cout<<x<<" "; } cout<<isEmpty(s,0)<<endl; for(int i=0;i<d;i++) { Pop(s,1,x); cout<<x<<" "; } cout<<isEmpty(s,1)<<endl; } }
基于栈的回文字符序列判断
描述
回文序列是正反读均相同的字符序列,如“abba”和“abdba”均是回文,但是“good”不是回文。请设计一个算法判定给定的字符序列是否为回文。
输入
多组数据,每组数据有一行。每一行为一个长度不定的字符序列A。当A为“0”时,输入结束。
输出
对于每组数据输出一行。若字符序列A是回文序列,则输出“YES”,否则输出“NO”。
输入样例 1
abba abdba good 0输出样例 1
YES YES NO#include<bits/stdc++.h> using namespace std; int main() { string s; while(cin>>s&&s!="0") { int top=-1; char a[1000]; for(int i=0;i<s.length();i++) { top++; a[top]=s[i]; } int flag=1; for(int i=0;i<s.length();i++) { if(a[top]==s[i]) { top--; } else { flag=0; break; } } if(flag) cout<<"YES"<<endl; else cout<<"NO"<<endl; } }
入栈和出栈的基本操作
描述
输入一个整数序列a1,a2,a3...,an。当ai不等于-1时将ai进栈;当ai=-1时,输出栈顶元素并将其出栈。
输入
多组数据,每组数据有两行,第一行为序列的长度n,第二行为n个整数,整数之间用空格分隔。当n=0时输入结束。
输出
对于每一组数据输出若干行。每行为相应的出栈元素。当出栈异常时,输出“POP ERROR”并结束本组数据的输出。
输入样例 1
5 1 2 -1 -1 1 5 1 -1 -1 2 2 0输出样例 1
2 1 1 POP ERROR
#include<bits/stdc++.h> using namespace std; int main() { int n; int a[10000]; int b[10000]; while(cin>>n&&n!=0) { for(int i=0;i<n;i++) { cin>>a[i]; } int top=-1; for(int i=0;i<n;i++) { if(a[i]!=-1) { top++; b[top]=a[i]; } else { if(top!=-1) { cout<<b[top]<<endl; top--; } else { cout<<"POP ERROR"<<endl; break; } } } } }
基于栈的可操作判断
描述
假设I和O分别代表入栈和出栈操作。栈的始态和终态均为空。入栈和出栈的操作序列可以表示为仅由I和O组成的序列,称可操作的序列为合法序列,否则称为非法序列。请设计一个算法,判断所给的操作序列是否合法。若合法输出“true”,反之输出“false”。
输入
多组数据,每组数据为一行长度不定的操作序列A。当A为“0”时,输入结束。
输出
对应每组数据输出一行。若序列A为合法序列输出“TRUE”,反之输出“FALSE”。
输入样例 1
IOIOIO IIOOOO 0输出样例 1
TRUE FALSE
#include<bits/stdc++.h> using namespace std; int main() { char s[1000]; while(cin>>s&&s[0]!='0') { int i=0; int j=0,k=0; int flag=1; while(s[i]!='\0') { if(s[i]=='I') { j++; } else if(s[i]=='O') { k++; if(k>j) { flag=0; } } i++; } if(j!=k||flag==0) { cout<<"FALSE"<<endl; } else { cout<<"TRUE"<<endl; } } }
基于栈的后缀算术表达式求值
描述
从键盘上输入一个后缀表达式,试编写算法计算表达式的值。规定:后缀表达式的长度不超过一行,以“=”作为输入结束,操作数之间用空格分隔,操作符只可能有+、−、*、/四种运算。
输入
多组数据,每组数据一行,对应一个后缀算术表达式,每个表达式均以“=”结尾。当表达式只有一个“=”时,输入结束。
输出
对于每组数据输出一行,为表达式的运算结果。
输入样例 1
1 2+8 2-7 4-/*= 1 2+= 1 2/= =
输出样例 1
6.00 3.00 0.50
#include<bits/stdc++.h> using namespace std; double Operate(double a,double b,char op) { if(op=='+') return a+b; else if(op=='-') return a-b; else if(op=='*') return a*b; else if(op=='/') return b/a; } int main() { char s[1000]; while(cin>>s&&s[0]!='=') { double n[1000]; int top=-1; for(int i=0;s[i]!='=';i++) { if(s[i]>=48&&s[i]<=57) { top++; n[top]=(double)s[i]-48; } else { double x=n[top]; top--; double y=n[top]; top--; top++; n[top]=Operate(x,y,s[i]); } } printf("%.2f\n",n[top]); } }
基于循环链表的队列的基本操作
描述
用带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(不设头指针)。实现该队列的入队出队以及判断队列是否为空操作。
输入
多组数据,每组数据有两行。第一行为两个整数n和m,n表示入队序列A的长度(n个数依次连续入队,中间没有出队的情况),m表示出队序列B的元素数量(m个数依次连续出队,中间没有入队的情况)。第二行为序列A(空格分隔的n个整数)。当n和m都等于0时,输入结束。
输出
对应每组数据输出一行。每行包括m+1个整数,前m个数代表出队序列B的各个整数,最后一个整数表示队列是否为空,队列为空输出0,不为空输出1。整数之间用空格分隔。
输入样例 1
5 3 1 3 5 3 6 4 4 -1 2 3 4 0 0输出样例 1
1 3 5 1 -1 2 3 4 0#include<bits/stdc++.h> using namespace std; typedef struct LNode { int data; LNode *next; }LNode,*LinkList; typedef struct { LNode *fro,*rear; }LinkQueue; void InitQueue(LinkQueue &q) { q.fro=q.rear=new LNode; q.fro->next=NULL; } void IsEmpty(LinkQueue &q) { if(q.fro==q.rear) cout<<"0"<<endl; else cout<<"1"<<endl; } void EnQueue(LinkQueue &q,int x) { LNode *s=new LNode; s->data=x; q.rear->next=s; q.rear=s; } void DeQueue(LinkQueue &q) { LNode *s=q.fro->next; cout<<s->data<<" "; q.fro->next=s->next; if(q.rear==s) { q.rear=q.fro; } free(s); } int main() { int n,m; while(cin>>n>>m&&n!=0&&m!=0) { int x; LinkQueue q; InitQueue(q); for(int i=0;i<n;i++) { cin>>x; EnQueue(q,x); } for(int i=0;i<m;i++) { DeQueue(q); } IsEmpty(q); } }
附加判定标志的循环队列的基本操作
描述
假设以数组Q[m]存放循环队列中的元素, 同时设置一个标志tag,以tag== 0和tag == 1来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“满”。试编写与此结构相应的插入(enqueue)和删除(dlqueue)算法。
输入
多组数据,每组数据有两行。第一行为一个整数n,n表示入队序列A的长度(n个数依次连续入队,中间没有出队的情况),第二行为序列A(空格分隔的n个整数)。当n=0时,输入结束。
输出
对应每组数据输出一行。依次输出队列中所有的整数,每两个整数之间用空格分隔。
输入样例 1
4 1 2 3 4 5 1 2 4 5 3 0输出样例 1
1 2 3 4 1 2 4 5 3
#include<bits/stdc++.h> using namespace std; typedef struct { int data[1000]; int fro,rear; int tag; }SqQueue; void InitQueue(SqQueue &q) { q.fro=q.rear=0; q.tag=0; } bool EnQueue(SqQueue &q,int x) { if(q.tag==1&&q.fro==q.rear) { return false; } q.data[q.rear]=x; q.rear++; if(q.tag==0) { q.tag=1; } return true; } bool DeQueue(SqQueue &q,int &x) { if(q.tag==0&&q.fro==q.rear) { return false; } x=q.data[q.fro]; q.fro++; if(q.tag==0) { q.tag=1; } return true; } int main() { int n; while(cin>>n&&n!=0) { int x; SqQueue q; InitQueue(q); for(int i=0;i<n;i++) { cin>>x; EnQueue(q,x); } for(int i=0;i<n-1;i++) { DeQueue(q,x); cout<<x<<" "; } DeQueue(q,x); cout<<x<<endl; } }
基于两端操作的循环队列的实现
描述
如果允许在循环队列的两端都可以进行插入和删除操作。构造一个循环队列,实现从队头入队,从队尾出队并输出。约定从队头入队时向下标小的方向发展,从队尾入队时则向下标大的方向发展。
输入
多组数据,每组数据有两行。第一行为一个整数n,n表示入队序列A的长度(n个数依次连续入队,中间没有出队的情况),第二行为序列A(空格分隔的n个整数)。当n等于0时,输入结束。
输出
对应每组数据输出一行。依次输出队列中所有的整数,每两个整数之间用空格分隔。
输入样例 1
5 1 2 3 4 5 2 1 4 0输出样例 1
1 2 3 4 5 1 4
#include<bits/stdc++.h> using namespace std; #define MAX 1000 typedef struct { int data[MAX]; int fro,rear; }SqQueue; void InitQueue(SqQueue &q) { q.fro=q.rear=0; } bool EnQueue(SqQueue &q,int x) { if((q.rear+1)%MAX==q.fro) { return false; } q.data[q.rear]=x; q.rear=(q.rear+1)%MAX; return true; } bool DeQueue(SqQueue &q,int &x) { if(q.fro==q.rear) { return false; } x=q.data[q.fro]; q.fro=(q.fro+1)%MAX; return true; } int main() { int n; while(cin>>n&&n!=0) { int x; SqQueue q; InitQueue(q); for(int i=0;i<n;i++) { cin>>x; EnQueue(q,x); } for(int i=0;i<n-1;i++) { DeQueue(q,x); cout<<x<<" "; } DeQueue(q,x); cout<<x<<endl; } }