之前学习了栈的基本操作,并且学习了栈的两种实现方式:链式存储和顺序存储(数组)。现在看看栈都有哪些应用。栈的一个主要应用是平衡符号。
初学者在编写代码并且编译时,难免会因为少写了一个')'和被编译器报错。也就是说,编译器会去匹配括号是否匹配。当你输入了一个'(',很自然编译器回去检查你是否有另一个')'符号与之匹配。如果所有的括号都能够成对出现,那么编译器是能够通过的。否则编译器会报错。例如字符序列“(a+b)”是匹配的,而字符序列"(a+b]"则不是。
在检测括号匹配的算法中使用到了栈,算法描述如下:创建一个空栈,读取字符序列直到结尾。如果字符是开放符号'(''[''{',将其入栈;如果是一个封闭符号')'']''}',则当栈为空时报错。否则,将栈顶元素弹出。如果弹出的符号不是对应的开放符号,则报错。当字符序列结束,判断栈是否为空,为空则报错。
下面是我的实现代码:
#include <stdio.h>
#include <stdlib.h>
#define Error(Str) fprintf(stderr,"%s\n",Str),exit(1)
struct Node
{
char elem;
struct Node *next;
};//栈的链表实现
typedef struct Node *Stack;
int CheckSymbol(Stack S);//检测平衡符号的函数
Stack CreateStack(void);/*创建一个空栈*/
void MakeEmpty(Stack);
int IsEmpty(Stack);//测试栈是否是空栈
void Push(char ,Stack);//入栈
void Pop(Stack);//出栈
char Top(Stack);//获取栈顶元素
void DisposeStack(Stack);//销毁栈
int main()
{
Stack S;
S=CreateStack();
if(CheckSymbol(S))
printf("wrong\n");
else
printf("right\n");
DisposeStack(S);
return(0);
}
int CheckSymbol(Stack S)
{
char ch;
printf("input characters as {,} or (,)or [,] \n");
printf("and # to quit\n");
while((ch=getchar())!='#')//输入平衡字符
{
if(ch=='{'||ch=='['||ch=='(') /*开放符号*/
Push(ch,S);
else if(ch=='}'||ch==']'||ch==')') /*封闭符号*/
{
if(IsEmpty(S)) /*栈里无字符*/
Error("stack is empty.");
else
{
switch(ch)
{
case '}':
if(Top(S)!='{')//不匹配
Error("not match");
else
break;//匹配成功
case ')':
if(Top(S)!='(')
Error("not match");
else
break;
case ']':
if(Top(S)!='[')
Error("not match");
else
break;
}
/*匹配成功,将栈中匹配成功的符号弹出*/
Pop(S);
}
}
}
if(!IsEmpty(S))//如果最后栈里还有字符,则说明未匹配完,即出错
Error("the stack is not empty last");
else
return 0;//成功
}
/*栈的基本操作--链表实现*/
Stack CreateStack(void) //创建空栈
{
Stack S;
S=(Stack )malloc(sizeof(struct Node));
if(S==NULL)
Error("out of space");
S->next=NULL;
MakeEmpty(S);
return S;
}
void MakeEmpty(Stack S)
{
if(S==NULL) //未创建栈
Error("must usr CreateStack first");
else
while(!IsEmpty(S))
Pop(S);
}
void Push(char ch,Stack S)
{
Stack tmp;
tmp=(Stack)malloc(sizeof(struct Node));
if(tmp==NULL)
Error("out of space");
else
{
tmp->elem=ch;
tmp->next=S->next;
S->next=tmp;
}
} // 压栈
void Pop(Stack S)
{
Stack tmp;
if(IsEmpty(S))
Error("empty stack");
else
{
tmp=S->next;
S->next=tmp->next;
free(tmp);
}
} //从栈弹出元素
char Top(Stack S)
{
if(!IsEmpty(S))
return S->next->elem;
Error("empty stack.");
return 0;
} //返回栈顶元素
void DisposeStack(Stack S)
{
if(S==NULL)
Error("no stack");
MakeEmpty(S);
free(S);
} //释放栈
int IsEmpty(Stack S)
{
return(S->next==NULL);
} //测试栈是否空栈