栈的介绍
栈是什么:
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
栈的特点:
其特殊之处在于栈底和栈顶,我们将新元素添加到栈中时,叫做压栈,也就是将新元素放在栈顶,当我们项删除元素时,也只能从栈顶开始删除,这个叫做出栈。也就是说我们添加删除元素时都只能从栈顶开始,这个就有些限制我们了。当我们想要用新元素替代栈顶元素时,栈这种东西时先出后入的。
栈相关算法:
1.进栈(PUSH)算法
①若TOP≥n时,则给出溢出信息,作出错处理(进栈前首先检查栈是否已满,满则溢出;不满则作②);
②置TOP=TOP+1(栈指针加1,指向进栈地址);
③S(TOP)=X,结束(X为新进栈的元素);
2.退栈(POP)算法
①若TOP≤0,则给出下溢信息,作出错处理(退栈前先检查是否已为空栈, 空则下溢;不空则作②);
②X=S(TOP),(退栈后的元素赋给X):
③TOP=TOP-1,结束(栈指针减1,指向栈顶)。
栈的相关实现:
我们在平时用栈时,有的人可能会直接用STL库里面的,用一个#include 头文件就可以了,那里面有相关实现函数。但是有的人为了节省运行时间,就会自己直接写一个栈类,然后自己直接用就行了。以下是我自己写的一个栈模板类,我们在里面想存什么数据都可以,但是如果说要存一个类的话,我们的输入输出赋值啥操作就需要我们去运用运算符重载了。
template <typename T>
class MyStack
{
public:
MyStack(int psize) //构造函数
{
size=psize;
myBuffer=new T[size];
top=0;
}
~MyStack() //析构函数
{
delete []myBuffer;
}
bool Empty() //判断是否为空
{
if(top==0)
{
return true;
}
else return false;
}
bool stackFull() //判断是否溢出
{
if(top==size)
{
return true;
}
else
{
return false;
}
}
void clear() //清空栈
{
top=0;
}
int stackLength()
{
return top;
}
void push(T elem) //入栈
{
if(!stackFull())
{
myBuffer[top]=elem;
top++;
}
}
void pop() //出栈
{
if(!Empty())
{
top--;
}
}
void stackTraverse(int n) //遍历输出两种方式
{
if(n==1){
for(int i=0;i<top;i++)
{
cout<<myBuffer[i]<<" ";
}
cout<<endl;
}
if(n==2)
{
for(int i=top-1;i>=0;i--)
{
cout<<myBuffer[i]<<" ";
}
cout<<endl;
}
}
T ptop() //访问栈顶元素·
{
return myBuffer[top-1];
}
private:
T *myBuffer; //栈空间指针
int size; //栈容量
int top; //栈元素个数
};
以上是一个比较完整的栈模板类,做题时可以利用里面的相关函数,不需要用到的自己也可以不用写了。
经典例子
进制转换:
进制转换这种算法相信大家都已经很清楚了,就是我们以前高中学过的除k取余法,然而呢,我们现在可以用栈来实现它,把每一个余数压入栈中,然后输出就可以了。
以下是核心代码:
char num[]="0123456789ABCDEF"; //考虑到十六进制转换时大于等于10的数需要分别用ABCDEF表示
MyStack<int> *stack = new MyStack<int>(30);
int N=1348;
cout<<"请输入数字:"<<endl;
cin>>N;
int mod=0;
int n;
cout<<"请输入你想要转换的进制数:"<<endl;
cin>>n;
while(N!=0)
{
mod=N%n;
stack->push(mod);
N=N/n;
}
while(!stack->Empty())
{
cout<<num[stack->ptop()];
stack->pop();
}
括号符匹配:
遍历字符串,遇到左括号就压入栈中,遇到右括号,就看栈顶是否有与之匹配的左括号,如果有,就让栈顶元素出栈,反之则不。这也慢慢执行下去,到最后再判断栈是否为空,若为空,则字符串合法,反之则不合法。如果说想要更加清楚的话,大家可以在纸上手动演示该过程,相信你这样可以更加理解栈。以下是核心代码:
MyStack<char> *stack = new MyStack<char>(30);
string str;
cin>>str;
for(int i=0;i<str.length();i++)
{
if(str[i]=='('||str[i]=='['||str[i]=='{')
{
stack->push(str[i]);
}
if(str[i]==')')
{
if(stack->ptop()=='(')
{
stack->pop();
}
}
if(str[i]==']')
{
if(stack->ptop()=='[')
{
stack->pop();
}
}
if(str[i]=='}')
{
if(stack->ptop()=='{')
{
stack->pop();
}
}
}
if(stack->Empty()) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
这是本人对栈的理解,希望能够对大家有所帮助。