top指针始终指向链表首元素。
设计要点:
类模板,抽象父类Stack的直接子类
在内部组合使用LinkList类,实现栈的链式存储。
只在单链表成员对象的头部进行操作。
#ifndef LINKSTACK_H_
#define LINKSTACK_H_
#include "Stack.h"
namespace WSlib
{
template <typename T>
class LinkStack:public Stack<T>
{
protected:
LinkList<T> m_list;
public:
void push(const T& e)
{
m_list.insert(0,e);
}
void pop()
{
if(m_list.length()>0)
{
m_list.remove(0);
}
else
{
THROW_EXCEPTION(InvalidOperationException,"no element in current stack");
}
}
T top() const
{
if(m_list.length()>0)
{
return m_list.get(0);
}
else
{
THROW_EXCEPTION(InvalidOperationException,"no element in current stack");
}
}
void clear()
{
m_list.clear();
}
int size()const
{
return m_list.length();
}
};
}
#endif
/*******************************************************************************
#include <iostream>
#include "LinkStack.h"
using namespace std;
using namespace WSlib;
class Test:public Wobject
{
public:
Test()
{
cout<<"Test()"<<endl;
}
~Test()
{
cout<<"~Test()"<<endl;
}
};
int main()
{
//StaticStack<Test,10> s;//调用10次构造函数,10次析构函数,由原生数组作为存储空间,创建时当然会调用对应泛指类型的构造函数
LinkStack<Test> s;
cout<<s.size()<<endl;
return 0;
}
*************************************************************************************/
栈的应用实践:
符号匹配问题:在c语言中有一些成对匹配出现的符号,
括号:(),{},[],<>
引号:‘’“”
如何实现编译器中的符号成对检测?
算法思路:从第一个字符开始扫描:当遇见普通字符时忽略,当遇到左符号时压入栈中,当遇到右符号时弹出栈顶符号,并 进行匹配。
结束:成功:所有字符扫描完毕,且栈为空。失败:匹配失败或所有字符扫描完毕但栈非空。
#include <iostream>
#include "LinkStack.h"
using namespace std;
using namespace WSlib;
bool is_left(char c)
{
return (c=='(')||(c=='[')||(c=='{')||(c=='<');
}
bool is_right(char c)
{
return (c==')')||(c==']')||(c=='}')||(c=='>');
}
bool is_quot(char c)
{
return (c=='\'')||(c=='\"');
}
bool is_match(char l,char r)
{
return ((l=='(')&&(r==')'))||
((l=='{')&&(r=='}'))||
((l=='<')&&(r=='>'))||
((l=='[')&&(r==']'))||
((l=='\'')&&(r=='\''))||
((l=='\"')&&(r=='\"'));
}
bool scan(const char* code)
{
LinkStack<char> s;
int i = 0;
bool ret=true;
code=(code==NULL)? "": code;
while(ret && (code[i] != '\0'))
{
if(is_left(code[i]))
{
s.push(code[i]);
}
else if(is_right(code[i]))
{
if((s.size()>0)&&is_match(s.top(),code[i]))
{
s.pop();
}
else
{
ret=false;
}
}
else if(is_quot(code[i]))
{
if((s.size()==0)|| !is_match(s.top(),code[i]))
{
s.push(code[i]);
}
else if(is_match(s.top(),code[i]))
{
s.pop();
}
}
i++;
}
return ret&&(s.size()==0);
}
int main()
{
cout<<scan("else if(is_quot(code[i])){if((s.size()==0)|| !is_match(s.top(),code[i])){s.push(code[i]);}else if(is_match(s.top(),code[i])){s.pop();}}i++;")<<endl;
return 0;
}
小结:链式栈的实现组合使用了单链表对象,在单链表的头部进行操作能够实现高效的入栈和出栈操作,栈后进先出的特性适用于检测成对出现的符号,栈非常适合于需要就近匹配的场合。
开放性问题:使用单链表对象实现链式栈时,为什么选择在单链表的头部进行操作?如果选择在尾部进行操作是否也能实现栈的功能?
202

被折叠的 条评论
为什么被折叠?



