栈的特点之一是FILO(先进后出),基于这个特点在这里给出栈的部分基础应用:
1:括号匹配;
所谓的括号匹配就是一个表达式中包括变量、常量、操作符、圆括号,圆括号可以嵌套, 编写程序判断表达式中的括号是否正确匹配。输入任意一个表达式,判断其中括号是否匹配。
利用栈的特性可以很简单的解决这个问题,对于一个表达式从第一个字符开始处理,如果遇到左括号就入站,如果遇到右括号就与栈顶元素匹配,如果右括号与栈顶元素无法匹配那么程序可以终止。因为很显然这个表达式的括号不匹配。而且程序的开始和结束时,括号匹配的表达式所对应的栈是空的。
例如《《(》》》
还有《《《》》
下面给出函数代码:
void Match(SqStack *s) { char ch; while((ch = getchar()) != '\n') { switch (ch) { case '(': Push(s,ch);break; case '<': Push(s,ch);break; case '[': Push(s,ch);break; case '{': Push(s,ch);break; case ')': if(GetTop(s) == '('){Pop(s);break;} else {printf("括号不匹配.\n");return;} case '>': if(GetTop(s) == '<'){Pop(s);break;} else {printf("括号不匹配.\n");return;} case ']': if(GetTop(s) == '['){Pop(s);break;} else {printf("括号不匹配。\n");return;} case '}': if(GetTop(s) == '{'){Pop(s);break;} else {printf("括号不匹配。\n");return;} } } if (IsEmpty(s)) printf("括号不匹配。\n"); else printf("括号匹配.\n"); }
这个函数可以处理的括号有四种< ( [ {}])>
里面有关于栈的函数在前面已经写过,这里还是把程序的完整代码贴出来好一些:
#include <stdio.h> #include <stdlib.h> #define STACK_INIT_SIZE 100 //栈空间的初始分配量 #define STACKINCREMENT 10 //存储空间的分配增量 typedef char SElemType; typedef struct { SElemType *base; //在构造栈之前和销毁栈之后,base的数值为NULL SElemType *top; //栈顶指针 int stacksize; //显示栈当前的容量 }SqStack; //创建一个空栈 int InitStack(SqStack *s); //销毁栈 int DestroyStack(SqStack *s); //清空栈 int ClearStack(SqStack *s); //判断栈是否为空栈 int StackEmpty(SqStack *s); //计算栈的长度 int StackLength(SqStack *s); //获取栈顶元素 int GetTop(SqStack *s); //将一个元素推入站内 int Push(SqStack *s,SElemType data); //将一个元素退出栈 int Pop(SqStack *s); //对于栈内的每一个元素调用函数 int StackTraverse(SqStack *s); int InitStack(SqStack *s) { s->base = (SElemType *)malloc(sizeof(SElemType)*STACK_INIT_SIZE); //为栈分配基础空间 if(!s->base)exit(1); //分配失败的话就退出 s->top = s->base; //栈顶指针指向栈底 s->stacksize = STACK_INIT_SIZE; //初始化栈的大小 return 1; } int Push(SqStack *s,SElemType data) { if(s->top-s->base >= s->stacksize) //如果栈的空间不够再增加 { s->base = (SElemType *)realloc(s->base,(s->stacksize + STACKINCREMENT)*sizeof(SElemType)); if(!s->base)exit(1); //在原来空间的基础上额外增加空间 s->top = s->base + s->stacksize; //栈顶指针加1 s->stacksize += STACKINCREMENT; //栈大小增加 } *s->top++ = data; //元素入栈,栈顶指针加1 return 1; //入栈成功 } int Pop(SqStack *s) { if(s->base == s->top) return 0; //如果栈为空栈返回出栈失败 (*--s->top); //栈顶指针减1 return 1; //出栈成功 } int GetTop(SqStack *s) { if(s->base == s->top) return 0; //空栈返回失败 return *(s->top-1); //返回栈顶元素 } int StackLength(SqStack *s) { SElemType *tmp = s->top; //设置临时变量和栈顶指针相同 int flag = 0; while(tmp != s->base) //栈顶指针逐个减1知道栈底 { flag ++; tmp--; } return flag; //返回栈的长度 } int DestroyStack(SqStack *s) { free(s->base); //释放掉栈的分配空间 s->base = s->top = NULL; //栈顶和栈底指向NULL s->stacksize = 0; //栈的长度还原为0 return 1; } int ClearStack(SqStack *s) { s->top = s->base; //栈清空最方便只需要将栈顶指针指向栈底 return 1; } int StackTraverse(SqStack *s) { SElemType *tmp = (s->top-1); if(s->top == s->base)return 0; while(1) { printf("%d ",*tmp); if(tmp == s->base) break; //这个地方我刚刚犯了一个错误就是忽视栈底base指针指向的区域也有一个数据 tmp--; } return 1; } int IsEmpty(SqStack *s) { if(s->base == s->top)return 0; else return 1; } void Match(SqStack *s) { char ch; while((ch = getchar()) != '\n') { switch (ch) { case '(': Push(s,ch);break; case '<': Push(s,ch);break; case '[': Push(s,ch);break; case '{': Push(s,ch);break; case ')': if(GetTop(s) == '('){Pop(s);break;} else {printf("括号不匹配.\n");return;} case '>': if(GetTop(s) == '<'){Pop(s);break;} else {printf("括号不匹配.\n");return;} case ']': if(GetTop(s) == '['){Pop(s);break;} else {printf("括号不匹配。\n");return;} case '}': if(GetTop(s) == '{'){Pop(s);break;} else {printf("括号不匹配。\n");return;} } } if (IsEmpty(s)) printf("括号不匹配。\n"); else printf("括号匹配.\n"); } int main() { SqStack s; //初始化栈并且创建栈 InitStack(&s); Match(&s); //清空栈 ClearStack(&s); //销毁栈 DestroyStack(&s); return 0; }