栈(LIFO)

1 栈的定义

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

 

2 栈的特点

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

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

3)后进先出。

 

3 栈的实现及关键点

3.1 顺序栈

3.1.1 关键点

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

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

3.1.2 实现

 1 #ifndef SQUENCESTACK_H
 2 #define SQUENCESTACK_H
 3 
 4 typedef int ElemType;
 5 
 6 class SquenceStack
 7 {
 8 private:
 9     ElemType* m_pData;
10     int m_stackSize;    //栈长
11     int m_top;    //栈顶指针
12 
13 public:
14     SquenceStack(int stackSize);
15     ~SquenceStack();
16     void ClearStack() { m_top = -1; }    //清空栈
17     bool Push(ElemType elem);    //压栈
18     bool Pop(ElemType* pElem);    //弹栈
19     bool VisitStack() const;    //顺序遍历栈
20     bool EmptyStack() const { return -1 == m_top; }    //判断是否为空栈
21 };
22 
23 #endif
 1 #include "pch.h"
 2 #include "SquenceStack.h"
 3 #include <iostream>
 4 
 5 SquenceStack::SquenceStack(int stackSize)
 6 {
 7     m_stackSize = stackSize;
 8     m_top = -1;
 9     m_pData = new ElemType[stackSize];
10 }
11 
12 SquenceStack::~SquenceStack()
13 {
14     delete[] m_pData;
15 }
16 
17 bool SquenceStack::Push(ElemType elem)    //压栈
18 {
19     if (m_stackSize - 1 == m_top)    //满栈
20         return false;
21     
22     ++m_top;
23     m_pData[m_top] = elem;
24 
25     return true;
26 }
27 
28 bool SquenceStack::Pop(ElemType* pElem)    //弹栈
29 {
30     if (EmptyStack())    //空栈
31         return false;
32 
33     *pElem = m_pData[m_top];
34     --m_top;
35 
36     return true;
37 }
38 
39 bool SquenceStack::VisitStack() const    //顺序遍历栈
40 {
41     if (EmptyStack())
42     {
43         std::cout << "The stack is Empty." << std::endl;
44         return false;
45     }
46         
47 
48     std::cout << "the element of stack: ";
49     for (int i = 0; i <= m_top; ++i)
50         std::cout << m_pData[i] << ' ';
51     std::cout << std::endl;
52     
53     return true;
54 }

测试代码:

 1 #include "pch.h"
 2 #include "SquenceStack.h"
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     SquenceStack stack(5);
10     stack.VisitStack();
11     stack.Push(0);
12     stack.Push(1);
13     stack.Push(2);
14     stack.Push(3);
15     stack.Push(4);
16     stack.VisitStack();
17     ElemType elem;
18     stack.Pop(&elem);
19     stack.Pop(&elem);
20     stack.VisitStack();
21 
22     return 0;
23 }

测试结果:

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个操作数,然后计算,再把计算完的结果压入操作数栈,继续比较;其中左括号直接进栈,遇到右括号时运算到匹配到左括号为止。

 

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

posted @ 2019-04-11 20:15  zpchya  阅读(825)  评论(0编辑  收藏  举报