栈的链式存储结构形象表示:
相比顺序结构,链式结构有一个很大的优点——插入和删除方便。在链栈中,栈就相对不会存在栈满的情况,因为可以一直的插入。出栈操作也变得很方便,只要将栈顶数据删除,释放掉该内存就好了。
一、进栈
进栈操作:
(1) 动态分配一个节点数据;
(2) 将该节点的指针指向原来的栈的栈顶位置;
(3) 修改栈顶的位置。
bool Push_L(LinkStack &S,ElemType e)
{
LinkStack p;
if ((p = (LinkStack)malloc(sizeof(LNode))) == NULL)
{
return false;
}
p->next = S;
S = p;
p->data = e;
return true;
}
二、出栈
出栈操作:
(1) 判断栈是否为空,非空继续,空则返回;
(2) 创建一个指向栈顶的指针p;
(3) 将栈顶指针向栈低移动一个位置;
(4) 删除p指向的空间,并释放该内存;
bool Pop_L(LinkStack &S,ElemType &e)
{
LinkStack p;
if (S != NULL)
{
e = S->data;
p = S;
S = p->next;
free(p);
return true;
}
else
{
return false;
}
}
三、栈的应用
假设一个算术表达式包含圆括号、方括号和花括号三种类型的括号,编写一个判别表达式中括号是否正确配对的算法。
例如:输入:{(a+b)*(c+d)/[2*(h+j)]}
输出:配对成功
输入:{(a+b)*(c+d)/[2*h+j)]
输出:配对失败
思想:使用栈的特点,从表达式的开头遍历整个表达式,每遇到一个正向括号就压栈,遇到反向的括号就弹栈,弹栈后比对弹栈的元素和栈顶元素是否配对,若配对就继续上述过程,如果不配对就直接退出。
void main()
{
LinkStack myStack;
char str[256],*pt;
char temp;
cout<<"Input a string!"<<endl;
cin.getline(str,256);
InitStack_L(myStack);
pt = str;
while (*pt != '\0')
{
switch(*pt)
{
case '(':
case '[':
case '{':
Push_L(myStack,*pt);
break;
case ')':
Pop_L(myStack,temp);
if (temp != '(')
{
cout<<"Not match!"<<endl;
system("pause");
return;
};
break;
case ']':
Pop_L(myStack,temp);
if (temp != '[')
{
cout<<"Not match!"<<endl;
system("pause");
return;
};
break;
case '}':
Pop_L(myStack,temp);
if (temp != '{')
{
cout<<"Not match!"<<endl;
system("pause");
return;
};
break;
default:
break;
}
pt++;
}
DestroyStack_L(myStack);
cout<<"Match!!"<<endl;
system("pause");
}