栈:一种最基本的数据存储的结构方式;
顺序栈:利用一组地址连续的存储单元依次存方自栈底到栈顶的数据元素。
栈最大的特点是先进后出。这种方式的存取速度比较快,仅次于直接位于CPU中的寄存器。
以下的代码是创建一个顺序栈,实现它的基本功能。并且通过检验匹配括号来实现栈的功能。
注意事项:
1,栈顶指针永远指向的是栈顶元素前一个空栈的地址。
2,栈底指针一直指向栈底,中途是不会发生变化的,当栈顶指针与栈底指针指向同一区域时,说明此时的栈为空栈。
我编译的时候遇到的最大的问题是在match函数中,开始没有添加if(c==10) continue;语句,一直运行不出结果,找的很奔溃,最后才发现,在main函数中输入元素个数以后按了回车,其实这也是一个字符,这就相当于间接的在match函数中的for循环中输入了字符,其实你本意是没有输入的,这样就导致栈永远不为空,永远匹配不成功,最后查阅资料百度才发现的问题,在for循环中设置一个continue语句,如果c=10,就跳出本次循环,记得是k<=l,比起始早进来一次所以多算一次。至于为什么c等于的是换行符而不是回车,我按键操作的是回车,我在if(c==10) continue;前设置了一个输出c,发现值为10而并非回车13.所以我也就直接用了10,这里的详细原因没有深入研究,因为当我们不知道是多少的时候直接输出一下字符就知道它的值了。这个问题找了好久,遇到类似的问题多加留意。
其余详解均写在代码注释中;
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define OK 1
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OVERFLOW -1
typedef int Status;
typedef Status ElemType;
typedef struct{
ElemType* base;
ElemType* top; //栈顶指针
int length; //用来记录栈的长度
}SqStack;
//以下四个函数基本实现了栈的基本功能;
Status InitStack(SqStack &s);
Status Push(SqStack &s,ElemType e);
Status Pop(SqStack &s,ElemType &e);
Status GetTop(SqStack &s,ElemType &e);
Status visit(ElemType a,ElemType b);
Status match(SqStack &s,ElemType l,Status (*visit)(ElemType a,ElemType b));
int main(int argc, char** argv){
SqStack s;
ElemType k,j=8;
ElemType c;
printf("请输入要匹配括号的个数:");
scanf("%d",&k);
if(InitStack(s)){
if(match(s,k,visit)){
if(s.top==s.base){
printf("这组括号检测到匹配格式成功;");
}else{
printf("这组括号检验到匹配格式有误;");
}
}
}
return 0;
}
//******创建一个初始长度为100的栈空间,让栈顶指针与栈底指针均指向栈底空间*****
Status InitStack(SqStack &s){ //初始化栈
s.base=(ElemType*) malloc (sizeof(ElemType)*STACK_INIT_SIZE); //申请一个长度为100的栈的空间
if(!s.base) exit(OVERFLOW);
s.top=s.base;
s.length=STACK_INIT_SIZE; //s.length是一个存储栈空间长度的容器,实时记录栈的长度;
return OK;
}
/*
1,考虑栈满的情况;
2,注意栈顶指针的变化情况;
*/
Status Push(SqStack &s,ElemType e){ //将元素e插入栈中
if(s.top-s.base>STACK_INIT_SIZE){ //说明栈满,需要增加栈空间容量
s.base=(ElemType*)realloc(s.base,(s.length+STACKINCREMENT)*sizeof(ElemType));
if(!s.base) exit (OVERFLOW);
s.top=s.base+s.length; //栈顶指针永远指向此时最后一个存有数据的栈空间
s.length+=STACKINCREMENT;
}
*(s.top++)=e;
return OK;
}
/*注意
1,栈顶与栈底位置情况。
2,栈顶指针是指向栈顶存有数据空间的上一个空空间的地址,而并非栈顶存有数据空间的地址。
*/
Status Pop(SqStack &s,ElemType &e){ //删除栈顶元素,用e返回删除的栈顶元素的值。
if(s.top==s.base) return ERROR;
s.top--;
e=*(s.top);
return OK;
}
//获得栈顶元素
Status GetTop(SqStack &s,ElemType &e){ //获得栈顶元素的值,用e返回其值。
if(s.top==s.base) return ERROR;
e=*(s.top-1);
//第一次写e=*(--s.top)是不对的,因为这样操作完栈顶指针指向了栈顶第一个存有数据的地址,而并未栈顶上一个空区域的地址。
return OK;
}
//实现检验括号匹配问题
Status visit(ElemType a,ElemType b){
if((a+1==b)||(a+2==b)){
return OK;
}else{
return ERROR;
}
}
Status match(SqStack &s,ElemType l,Status (*visit)(ElemType a,ElemType b)){
Status j,k,m;
char c;
for(k=0;k<=l;k++){
c=getchar();
//printf("%d",c);
if(c==10) continue;
switch(c){
case '(':m='(';break;
case ')':m=')';break;
case '[':m='[';break;
case ']':m=']';break;
case '{':m='{';break;
case '}':m='}';break;
}
if(GetTop(s,j)){
if(visit(j,m)){
Pop(s,j);
}else{
Push(s,m);
}
}else{
Push(s,m);
}
}
return OK;
}
运行截图: