1. 程式人生 > >棧和佇列的基本操作的實現

棧和佇列的基本操作的實現

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("該字串不中心對稱");
}