1 栈的定义

栈是限定在表尾进行插入和删除操作的线性表。

2 栈的特点

1)栈是特殊的线性表,线性表也具有前驱后继性;

2)栈的插入和删除操作只能在表尾即栈顶进行;

3)后进先出。

3 栈的实现及关键点

3.1 顺序栈

3.1.1 关键点

1)顺序栈用数组实现,可以将栈底和索引为0的数组空间对齐以降低插入删除操作的空间复杂度;

2)保持栈顶指针top和数组索引一致可降低操作复杂度,空栈的条件是-1 == top,满栈的条件为 栈长-1 == top。

3.1.2 实现

 #ifndef SQUENCESTACK_H
#define SQUENCESTACK_H typedef int ElemType; class SquenceStack
{
private:
ElemType* m_pData;
int m_stackSize; //栈长
int m_top; //栈顶指针 public:
SquenceStack(int stackSize);
~SquenceStack();
void ClearStack() { m_top = -; } //清空栈
bool Push(ElemType elem); //压栈
bool Pop(ElemType* pElem); //弹栈
bool VisitStack() const; //顺序遍历栈
bool EmptyStack() const { return - == m_top; } //判断是否为空栈
}; #endif
 #include "pch.h"
#include "SquenceStack.h"
#include <iostream> SquenceStack::SquenceStack(int stackSize)
{
m_stackSize = stackSize;
m_top = -;
m_pData = new ElemType[stackSize];
} SquenceStack::~SquenceStack()
{
delete[] m_pData;
} bool SquenceStack::Push(ElemType elem) //压栈
{
if (m_stackSize - == m_top) //满栈
return false; ++m_top;
m_pData[m_top] = elem; return true;
} bool SquenceStack::Pop(ElemType* pElem) //弹栈
{
if (EmptyStack()) //空栈
return false; *pElem = m_pData[m_top];
--m_top; return true;
} bool SquenceStack::VisitStack() const //顺序遍历栈
{
if (EmptyStack())
{
std::cout << "The stack is Empty." << std::endl;
return false;
} std::cout << "the element of stack: ";
for (int i = ; i <= m_top; ++i)
std::cout << m_pData[i] << ' ';
std::cout << std::endl; return true;
}

测试代码:

 #include "pch.h"
#include "SquenceStack.h"
#include <iostream> using namespace std; int main()
{
SquenceStack stack();
stack.VisitStack();
stack.Push();
stack.Push();
stack.Push();
stack.Push();
stack.Push();
stack.VisitStack();
ElemType elem;
stack.Pop(&elem);
stack.Pop(&elem);
stack.VisitStack(); return ;
}

测试结果:

栈(LIFO)-LMLPHP

3.2 两栈共享空间

3.2.1 适用条件

当两个栈的空间需求有相反关系时,也就是一个栈增长的同时另一个栈在缩短。(增长收缩的快慢应该相同)

3.2.2 实现与关键点

用一个数组来存储两个栈。数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标0处;另一个栈的栈底为数组的末端,即下标为数组长度n-1处。

那么栈1为空时,top1等于-1;栈2为空时,top2等于n;栈满的条件为top1 + 1 == top2。

3.3 链栈

3.3.1 关键点

1)单链表的头指针是必须的,而栈的栈顶指针也是必须的,自然的,可以将头指针和栈顶指针合二为一;

2)链栈为空的条件为nullptr == top,由于只在栈顶进行操作,所以在链表中为了统一操作的哨兵结点失去了作用。

3.3.2 实现

略。

4 栈的应用场景

4.1 四则运算表达式

规则:通过两个栈来实现,其中一个保存操作数的栈,另一个保存运算符的栈。当我们从左到右遍历表达式,当遇到数字,我们就直接压如操作数栈;当遇到运算符,就与运算符栈的栈顶元素进行比较。如果比运算符栈顶元素的优先级高,就将当前运算符压入栈;如果比运算符栈顶元素的优先级低或者相同,从运算符栈中取栈顶运算符,从操作数栈的栈顶取2个操作数,然后计算,再把计算完的结果压入操作数栈,继续比较;其中左括号直接进栈,遇到右括号时运算到匹配到左括号为止。

该篇博客是自己的学习博客,水平有限,如果有哪里理解不对的地方,希望大家可以指正!

04-30 22:49