栈是常用的一种线性数据结构。

栈的修改与访问是按照后进先出的原则进行的,因此栈通常被称为是后进先出(last in first out)表,简称 LIFO 表。栈就像一摞盘子,最先放的压在最下面,最后放的留在最上面,拿的时候也是最上面的先被拿走。

栈只能在某一端插入和删除元素

使用数据模拟栈

int a[1001],pos=0;//数据模拟栈
a[++pos]=x;//入栈 push
if(pos>0)
    pos--;//弹出元素 pop
int u=a[pos];//取出栈顶元素 top
pos=0;//清空栈内元素 clear

C++ STL 中的栈

C++ 中的 STL 也提供了一个容器 stack

STL 中的 stack 容器提供了一众成员函数以供调用,其中较为常用的有:

  • 元素访问

    • st.top() 返回栈顶
  • 修改

    • st.push() 插入传入的参数到栈顶
    • st.pop() 弹出栈顶
  • 容量

    • st.empty() 返回是否为空
    • st.size() 返回元素数量
stack<int> s;
s.push(x);//入栈
s.pop();//出栈
if(s.size()>0)
  int u=s.top();//取出栈顶元素

队列

队列(queue)是一种具有「先进入队列的元素一定先出队列」性质的表。由于该性质,队列通常也被称为先进先出(first in first out)表,简称 FIFO 表。队列就像排队买票,先来的先买,后来的后买。

队列只能在一端插入元素,另一端删除元素

数组模拟队列

通常用一个数组模拟一个队列,用两个变量标记队列的首尾。

const int maxsize=105;
int q[maxsize], head=1, tail=0,size;//头尾指针、队列元素个数
//tail++;
tail=(tail+1)%maxsize;//循环队列
q[tail]=x;//入队 
size++;
q[head];//访问队头元素
q[tail];//访问队尾元素
head++;//出队 删除元素 
size()--;

循环队列

使用数组模拟队列会导致一个问题:随着时间的推移,整个队列会向数组的尾部移动,一旦到达数组的最末端,即使数组的前端还有空闲位置,再进行入队操作也会导致溢出(这种数组里实际有空闲位置而发生了上溢的现象被称为「假溢出」)。

解决假溢出的办法是采用循环的方式来组织存放队列元素的数组,即将数组下标为 0 的位置看做是最后一个位置的后继。(数组下标为 x 的元素,它的后继为 (x + 1) % SIZE)。这样就形成了循环队列。

双栈模拟队列

还有一种冷门的方法是使用两个 栈 来模拟一个队列。

这种方法使用两个栈 F, S 模拟一个队列,其中 F 是队尾的栈,S 代表队首的栈,支持 push(在队尾插入),pop(在队首弹出)操作:

  • push:插入到栈 F 中。
  • pop:如果 S 非空,让 S 弹栈;否则把 F 的元素倒过来压到 S 中(其实就是一个一个弹出插入,做完后是首尾颠倒的),然后再让 S 弹栈。

容易证明,每个元素只会进入/转移/弹出一次,均摊复杂度 O(1)。

C++ STL 中的队列

STL 中的 queue 容器提供了一众成员函数以供调用。其中较为常用的有:

  • 元素访问
    • q.front() 返回队首元素
    • q.back() 返回队尾元素
  • 修改
    • q.push() 在队尾插入元素
    • q.pop() 弹出队首元素
  • 容量
    • q.empty() 队列是否为空
    • q.size() 返回队列中元素的数量
queue<int> q;
q.push(x);//入队
q.front();//返回队头元素
if(!q.empty())
    q.pop();//出队
Copyright ©图灵之星 2024,转载需注明出处该文件修订时间: 2025-03-17 21:11:46

results matching ""

    No results matching ""