栈和队列的基本操作的实现

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("该字符串不中心对称");
}

猜你喜欢

转载自blog.csdn.net/J_SUNV/article/details/84307746