棧和佇列的基本操作的實現
阿新 • • 發佈:2018-11-29
1.
實驗目的
熟練掌握棧和佇列的抽象資料型別,能在相應的應用問題中正確選用它們,熟練掌握棧和佇列的實現方法(順序和鏈式),兩種儲存結構和基本操作的實現演算法,注意空和滿的判斷條件及它們的描述方法,掌握迴圈佇列與其它順序結構實現上的不同及解決辦法,熟悉各種佇列的基本操作在迴圈佇列上的實現
2.實驗內容
(1)用棧實現括號匹配的檢驗
(2)用棧實現形如[email protected]+a#的中心對稱的字元序列的檢驗。
(3)用佇列實現形如[email protected]+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("該字串不中心對稱");
}