1.
实验目的
熟练掌握栈和队列的抽象数据类型,能在相应的应用问题中正确选用它们,熟练掌握栈和队列的实现方法(顺序和链式),两种存储结构和基本操作的实现算法,注意空和满的判断条件及它们的描述方法,掌握循环队列与其它顺序结构实现上的不同及解决办法,熟悉各种队列的基本操作在循环队列上的实现
2.实验内容
(1)用栈实现括号匹配的检验
(2)用栈实现形如a+b@b+a#的中心对称的字符序列的检验。
(3)用队列实现形如a+b@b+a#的中心对称的字符序列的检验
选择合适的存储结构(顺序栈或链式栈)表示栈,给出其定义,在上述存储结构上实现栈的基本操作:初始化、置栈空、入栈、出栈、取栈顶元素等。选择合适的存储结构(循环队列)表示队列,解决队空、队满判断条件相同的矛盾,实现基于循环队列的存储结构的基本操作,初始化、队空/满判断,入队、出队、取队头元素、求队列长度等,对所写出的算法进行时间复杂度分析
问题1:
#include<stdio.h>
#include<stdlib.h>
#define STACK_INIT_SIZE 10
#define STACKINCREMENT 5
#define OVERFLOW -1
#define ERROR 0
#define OK 1
#define TRUE 1
#define FALSE 0
typedef char SElemType;
typedef int Status;
typedef struct{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
//初始化一个空栈
Status InitStack(SqStack *s){
s->base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!s->base) exit(OVERFLOW);
s->top = s->base;
s->stacksize = STACK_INIT_SIZE;
return OK;
}
//销毁栈
Status DestroyStack(SqStack *s){
free(s->base);
s->base = s->top = NULL;
s->stacksize = 0;
return OK;
}
//清空栈
Status ClearStack(SqStack *s){
s->top = s->base;
return OK;
}
//判空
Status StackEmpty(SqStack *s){
return s->base==s->top;
}
//求栈的长度
int StackLength(SqStack *s){
return s->top-s->base;
}
//得到栈顶元素
Status GetTop(SqStack s,SElemType *e){
if(!StackEmpty(&s)){
printf("空栈!\n");
return ERROR;
}
*e = *(s.top-1);
return OK;
}
//入栈
Status Push(SqStack *s,SElemType e){
if(s->top-s->base>=s->stacksize){
s->base = (SElemType *)realloc(s->base,(STACKINCREMENT+s->stacksize)*sizeof(SElemType));
if(!s->base) exit(0);
s->top = s->base+s->stacksize;
s->stacksize += STACKINCREMENT;
}
*s->top++ = e;
return OK;
}
//出栈
Status Pop(SqStack *s,SElemType *e){
if(s->base==s->top){
printf("空栈!\n");
return ERROR;
}
*e = *--s->top;
return OK;
}
//遍历栈中的元素
Status StackTraverse(SqStack *s,Status(*visit)(SElemType)){
for(SElemType *i = s->base;i<s->top;i++)
if(!visit(*i)) return ERROR;
return OK;
}
//输出某个元素值
Status visit(SElemType e){
printf("%c ",e);
return OK;
}
//括号匹配的检查
Status BracketsMatch(SqStack *s){//s是用存储括号的栈
InitStack(s);//初始化一个空栈
printf("请输入英文括号表达式:(输入#作为结束符)\n");
char c = getchar(),cha;
while(c!='#'){
if(c=='('||c=='{'||c=='['){
Push(s,c);//如果是左括号 入栈
}else{
if(StackEmpty(s)){//栈空的时候 右括号入栈说明匹配失败
printf("匹配失败!\n");
return ERROR;
}else{
//不空的时候出栈(不是得到栈顶元素 因为这个元素如果匹配成功的话就要把它从栈里删除)一个元素 若匹配则跳过 若不匹配则失败
Pop(s,&cha);
if(!((cha=='('&&c==')')||(cha=='{'&&c=='}')||(cha=='['&&c==']'))){
printf("匹配失败!\n");
return ERROR;
}
}
}
c = getchar();
}
if(StackEmpty(s)){
printf("匹配成功!\n");
return OK;
}else{
printf("匹配失败3!\n");
return ERROR;
}
}
main(){
SqStack s;
BracketsMatch(&s);
}
问题2:
#include<stdio.h>
#include<stdlib.h>
#define STACK_INIT_SIZE 10
#define STACKINCREMENT 5
#define OVERFLOW -1
#define ERROR 0
#define OK 1
#define TRUE 1
#define FALSE 0
typedef char SElemType;
typedef int Status;
typedef struct{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
//初始化一个空栈
Status InitStack(SqStack *s){
s->base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!s->base) exit(OVERFLOW);
s->top = s->base;
s->stacksize = 0;
return OK;
}
//销毁栈
Status DestroyStack(SqStack *s){
free(s->base);
s->base = s->top = NULL;
s->stacksize = 0;
return OK;
}
//清空栈
Status ClearStack(SqStack *s){
s->top = s->base;
return OK;
}
//判空
Status StackEmpty(SqStack *s){
return s->base==s->top;
}
//求栈的长度
int StackLength(SqStack *s){
return s->top-s->base;
}
//得到栈顶元素
Status GetTop(SqStack s,SElemType *e){
if(!StackEmpty(&s)){
printf("空栈!\n");
return ERROR;
}
*e = *(s.top-1);
return OK;
}
//入栈
Status Push(SqStack *s,SElemType e){
if(s->top-s->base>=s->stacksize){
s->base = (SElemType *)realloc(s->base,(STACKINCREMENT+s->stacksize)*sizeof(SElemType));
if(!s->base) exit(OVERFLOW);
s->top = s->base+s->stacksize;
s->stacksize += STACKINCREMENT;
}
*s->top++ = e;
return OK;
}
//出栈
Status Pop(SqStack *s,SElemType *e){
if(s->base==s->top){
printf("空栈!\n");
return ERROR;
}
*e = *--s->top;
return OK;
}
//遍历栈中的元素
Status StackTraverse(SqStack *s,Status(*visit)(SElemType)){
for(SElemType *i = s->base;i<s->top;i++)
if(!visit(*i)) return ERROR;
return OK;
}
//输出某个元素值
Status visit(SElemType e){
printf("%c ",e);
return OK;
}
//判断字符串是否中心对称
//前半部分入栈 然后一一出栈与后半部分字符一个一个比较
int Match(SElemType *a){//将一串字符的首地址传入进来
SElemType *p = a,e;
SqStack s;
InitStack(&s);
while(*p!='@'){
Push(&s,*p);
p++;
}
p++;//自增之前是指向@的 自增之后指向另一半字符串的首字母
while(*p!='#'){
Pop(&s,&e);
if(e!=*p){
printf("此字符串不中心对称!\n");
return ERROR;
}
p++;
}
if(*p=='#'&&StackEmpty(&s)){
printf("此字符串中心对称!\n");
return OK;
}else{
printf("此字符串不中心对称!\n");
return ERROR;
}
}
main(){
SElemType a[20];
printf("请输入一段以#为结束符的字符串(以@作为中心对称的标准):\n");
scanf("%s",a);
Match(a);
}
问题3:
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define MAXSIZE 50
//输入受限的双端队列 只允许在队尾插入
typedef int QElemType;
typedef int Status;
typedef struct{
QElemType *base;//队列的基地址
int front;//队头下标 相当于队头指针 指向队列头元素
int rear;//队尾下标 指向队列尾元素的下一个位置
}SqQue;
//构造一个空的循环队列
Status InitQueque(SqQue *q){
q->base = (QElemType *)malloc(MAXSIZE*sizeof(QElemType));
if(!q->base) exit(OVERFLOW);
q->front = q->rear = 0;//空队列 两指针均指向下表为0的位置
return OK;
}
//销毁队列
Status DestroyQueQue(SqQue *q){
if(q->base) free(q->base);
q->base = NULL;
q->front = q->rear = 0;
return OK;
}
//清空队列
Status ClearQueque(SqQue *q){
q->rear = q->front;
return OK;
}
//判空
Status QuequeEmpty(SqQue *q){
return q->front==q->rear;
}
//求队列中的元素个数
int QuequeLength(SqQue *q){
return (q->rear-q->front+MAXSIZE)%MAXSIZE;
}
//返回队头元素
Status GetHead(SqQue *q,QElemType *e){
if(q->front==q->rear){
printf("队列为空!\n");
return ERROR;
}
*e
= q->base[q->front];
return OK;
}
//入队列
Status EnQueque(SqQue *q,QElemType e){
if((q->rear+1)%MAXSIZE==q->front){
printf("队列已满!\n");
return ERROR;
}
q->base[q->rear] = e;
q->rear = (q->rear+1)%MAXSIZE;
return OK;
}
//从队头出队列
Status DeQuequeFront(SqQue *q,QElemType *e){
if(q->rear==q->front) return ERROR;
*e = q->base[q->front];
q->front = (q->front+1)%MAXSIZE;
return OK;
}
//从队尾出队列
Status DeQuequeRear(SqQue *q,QElemType *e){
if(q->front==q->rear) return ERROR;
*e = q->base[q->rear-1];
q->rear = (q->rear-1)%MAXSIZE;
return OK;
}
//输出某个值
Status visit(QElemType e){
printf("%d ",e);
return OK;
}
//遍历队列
Status QuequeTraverse(SqQue *q,Status (*visit)(QElemType e)){
if(q->front==q->rear){
printf("空队列!\n");
return ERROR;
}else{
int i=q->front;
while(i!=q->rear){
visit(q->base[q->rear]);
i = (i+1)%MAXSIZE;
}
return OK;
}
}
//判断是否中心对称
//从队头和队尾同时匹配删除元素 如果一直匹配成功并且最后队列为空的话 就是中心对称
int Match(char *a){
SqQue s;
QElemType f,r;
char *c=a;
InitQueque(&s);
while(*c!='@'&&*c!='#'&&*c!='\000'){
EnQueque(&s,*c);
c++;
}
if(*c=='#'||*c=='\000') return FALSE;
c++;//跳过@继续入队列
while(*c!='#'&&*c!='\000'){
EnQueque(&s,*c);
c++;
}
while(s.front!=s.rear){
//在删除时 如果返回了ERROR就说明是空对列 说明没有两两配对 有单独的一个元素被落下了
if(!DeQuequeFront(&s,&f)) return FALSE;
if(!DeQuequeRear(&s,&r)) return FALSE;
if(f!=r) return FALSE;
}
if(QuequeEmpty(&s)) return TRUE;
}
main(){
printf("请输入一段以'#'为结束符的字符串(以@为中心对称的标准):\n");
char a[50];
scanf("%s",a);
if(Match(a)) printf("该字符串中心对称");
else printf("该字符串不中心对称");
}