/*这里采用的是带有头节点(s)的单链表实现:
链栈的4要素:
(1)栈空条件:s->next=NULL
(2)栈满条件:不考虑
(3)进栈e操作:将包含e的节点插入到头节点之后
(4)退栈操作:取出头节点之后的节点的元素并删除之*/
//链栈中的数据节点的类型LiStack定义如下:
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
typedef char ElemType;
typedef struct linknode
{
ElemType data;//数据域
struct linknode *next;//指针域
}LiStack;
//初始化链栈
void InitStack(LiStack *&s)
{
s = (LiStack*)malloc(sizeof(LiStack));
s->next = NULL;
}
//销毁栈
/*销毁操作,链的操作都是设置两个指针,依次遍历整个链,释放节点*/
void DestroyStack(LiStack *&s)
{
LiStack *p = s;
LiStack *q = p->next;
while (q != NULL)
{
free(p);
p = q;
q = p->next;
}
free(p);//此时栈指向尾结点,释放其空间
}
//判断栈是否为空
bool StackEmpty(LiStack *s)
{
if (s->next == NULL)
{
return true;
}
}
//进栈Push:将新数据节点插入到头节点之后
//注意:在链插入操作时,一定要记住首先要为插入数据创造节点
void Push(LiStack *&s, ElemType e)
{
LiStack *p;
p = (LiStack*)malloc(sizeof(LiStack));
p->data = e;//新建元素e对应的节点
p->next = s->next;//插入p节点作为开始节点
s->next = p;
}
//出栈Pop:在栈不为空的条件下,将头节点的后续数据节点的数据域赋给e,然后将其删除
//注意:千万不要忘记释放掉你删除的那个节点
bool Pop(LiStack *&s, ElemType &e)
{
if (s->next == NULL)
{
return false;
}
LiStack *p = s->next;
e = p->data;
s->next = p->next;
free(p);
return true;
}
//取栈顶元素
bool GetTop(LiStack *s, ElemType &e)
{
if (s->next == NULL)
{
return false;
}
e = s->next->data;
return true;
}
//括号匹配
bool Match(ElemType str[], int n)
{
LiStack *s;
int i = 0;
ElemType e;
InitStack(s);
bool match = true;
while (i < n&&match)
{
if (str[i] == '(') //'('单引号是char类型,"("双引号是const char类型
{
Push(s, str[i]);
}
else if (str[i] == ')')
{
if (GetTop(s, e)==true)
{
if (e != '(')
{
match=false;
}
else
Pop(s, e);
}
else
match=false;
}
i++;
}
if (StackEmpty(s)!=true)
{
match = false;
}
DestroyStack(s);
return match;
}
int main()
{
LiStack *s;
int i = 5;
ElemType str[100];
while (i > 0)
{
cin >> str;
cout << strlen(str) << endl;
if (Match(str, strlen(str)))
{
cout << "括号匹配" << endl;
}
else
cout << "不匹配" << endl;
i--;
}
return 0;
}