受限才安全-栈和队列

79 阅读4分钟

栈(Stack)和队列(Queue)都是一种特殊的线性表。

为了模拟现实世界的规则,为普通的线性表增加了一些约束。这些约束可以使我们的操作安全,符合语义,符合语义的操作更方便。

原则

栈的基本思想是后进先出(LIFO),在计算机科学中被形式化,并被广泛应用于算法设计、操作系统、编程语言等领域。例如,函数调用的执行过程就是一个典型的栈结构,函数的调用和返回就对应着栈的压入和弹出操作。

它遵循先进先出(FIFO,First In First Out)的原则。就像我们在超市结账时排队一样,先到的人先结账,后到的人需要排在队伍的末尾等待。

1F04749D-D46F-4707-A25E-4B8866E3F1C8.png

栈和队列是一种强大而灵活的数据结构,它在许多不同类型的系统中都有广泛应用。理解和掌握栈和队列的概念可以帮助我们解决很多有趣的问题。

栈和队列的基本操作

栈的基本操作

  1. Push(压入) :将一个元素放入栈的顶部。
  2. Pop(弹出) :移除栈顶的元素,并返回这个元素的值。
  3. Peek/Top(查看栈顶) :返回栈顶元素的值,但不移除这个元素。
  4. IsEmpty(判断栈是否为空) :如果栈内没有元素,返回True,否则返回False。

队列的基本操作

  1. Enqueue(入队) :将一个元素添加到队列的末尾。
  2. Dequeue(出队) :移除队列头部的元素,并返回这个元素的值。
  3. Peek/Front(查看队头) :返回队列头部元素的值,但不移除这个元素。
  4. IsEmpty(判断队列是否为空) :如果队列内没有元素,返回True,否则返回False。

实现

这里需要强调,栈和队列是一种偏应用层的结构,从大分类上它是线性表,从实现上他可以使用数组方式【顺序存储】,也可以使用链表【链式存储】

A541F756-F280-4B37-A40F-139F58E7D52C.png

另外栈和队列直接也可以相互实现,即利用栈实现队列,用队列实现栈。

栈的变种

  1. 单调栈

单调栈是一种特殊的栈结构,它的特点是栈内元素保持单调性,可以是单调递增也可以是单调递减。

单调栈常常用于解决一类与邻近元素关系相关的问题,例如寻找数组中每个元素的下一个更大元素或下一个更小元素。

以下是单调栈的基本操作:

  1. Push(压入) :在压入新元素时,会不断地将栈顶元素弹出,直到栈顶元素满足单调性要求,然后再将新元素压入栈中。例如,在单调递增栈中,如果新元素大于栈顶元素,就将栈顶元素弹出,直到栈顶元素小于新元素,然后再将新元素压入栈中。
  2. Pop(弹出) :移除栈顶的元素,并返回这个元素的值。
  3. Peek/Top(查看栈顶) :返回栈顶元素的值,但不移除这个元素。
  4. IsEmpty(判断栈是否为空) :如果栈内没有元素,返回True,否则返回False。

74AD5805-E611-4B06-BC46-B9F6EBD57771.png

单调栈的一个重要应用是解决"下一个更大元素"或"下一个更小元素"的问题。例如,给定一个数组,找出数组中每个元素右边第一个比它大的元素。这类问题可以通过单调栈在O(n)的时间复杂度内解决。

队列的变种

  1. 双端队列
  2. 循环队列

循环队列(Circular Queue)是一种特殊的队列,特点是在物理结构上形成一个环(逻辑上的环),队尾的下一个位置就是队头。当队列满时,如果继续出队,就可以在队头的位置再次入队。这种操作方式充分利用了数组空间,避免了线性队列出队后导致的空间浪费。

201BA2E9-64C7-4376-B203-2C159F272197.png

值得注意的是队列判空,判满的条件

队列为空的判断条件为 head == tail

队列满的条件为 (tail+1)%n=head

  1. 优先级队列

经典应用

去除重复字母

删除字符串中的所有相邻重复项

滑动窗口最大值

前 K 个高频元素