算法精讲学习笔记 队列和栈

1.队列和栈的基本性质

(1)栈是先进后出的,队列是先进先出的
(2)栈和队列在实现结构上可以有数组和链表两种形式
数组结构实现比较容易;
链接结构比较复杂,因为牵扯很多指针操作;
(3)栈结构的操作
pop操作,从栈顶弹出一个元素;
也可以只访问栈顶元素而不弹出,也就是top或者peek操作;
push操作,从栈顶压入一个元素;
size操作,返回栈中的元素个数;
(4)队列的操作
与栈操作不同,push操作时在队头加入元素,
pop操作,是从队列尾部弹出一个元素。
队列和栈的基本操作,都是时间复杂度为O(1)。

栈可以理解为一条射线,底部是固定的,元素的进出栈只能从栈顶进行;
队列可以理解为一条直线,操作从两端进行,但是一端负责进队,一端负责出队;
还有一种结构是双端队列,两端都可以进出元素,比如Java中的Deque;
另外还有优先级队列,根据元素的优先级值,决定元素的弹出顺序,
优先级队列是堆结构,不是线性结构。

(5)深度优先遍历(DFS)和宽度优先遍历(BFS)
深度优先遍历可以用栈实现;
宽度优先遍历可以用队列实现,也就是经常说的树的层次遍历;
(6)平时使用的递归函数实际上用到了系统提供的函数栈,递归的过程可以看做递归函数
依次进入函数栈的处理过程,所有用递归函数可以做的过程都一定可以用非递归的方式实现。


2.实现支持getMin操作的栈结构

要求pop、push、getMin操作的时间复杂度都是O(1),
设计的栈类型可以使用现成的栈结构。

使用两个栈结构,一个stackData栈用来保存栈中元素,用法和普通栈一样,
另一个stackMin栈用来保存每一步操作的最小值,根据入栈方式的不同,有两种设计方案:
(1)弹出时需要判断
push操作元素依次保存到stackData栈,只有当前数小于等于(注意等于也要入栈)stackMin的栈顶时,才压入StackMin。


pop弹出时,StackData首先弹出,假设弹出value,去比较value和StackMin的栈顶元素,如果value大于StackMin栈顶,不作操作,如果等于StackMin栈顶,StackMin弹出当前栈顶(肯定不会小于)。这样操作,StackMin栈顶始终记录StackData的最小值。
(2)弹出时同步弹出
push操作元素依次保存到stackData栈,当前数小于stackMin的栈顶时,将当前数压入StackMin,否则大于等于栈顶时,重复压入当前stackMin的栈顶。

算法精讲学习笔记 队列和栈_第1张图片
(3)相比较,方案一压入时稍省空间,略费时间(需要比较);方案二稍费空间,略省时间。

 

3.使用两个栈实现队列

编写一个类,只能用两个栈结构实现队列,支持队列的基本操作(add/poll/peek)操作。
(1)使用两个栈结构,一个StackPush用来做压入栈,一个StackPop用作弹出栈。
初始化压入完成时,只要将StackPush的全部数据依次倒入到StackPop,数据的顺序就完全颠倒了,接下来弹出时就符合队列的性质了。

算法精讲学习笔记 队列和栈_第2张图片
(2)需要注意的,考虑几个实例即可
StackPush向StackPop中倒数据时必须一次倒完;
如果StackPop中有数据,必须等待StackPop完全弹出清空后再倒入数据;

4.栈的就地逆序问题

实现一个栈的逆序,但是只能用递归函数和这个栈本身的操作来实现,不能使用额外的数据结构。

5.栈的排序问题

一个栈中元素类型为整型,现在对该栈从栈顶到栈底从大到小排序,可以申请一个栈,不能申请额外的数据结构。

6.双端队列解决滑动窗口问题

(1)普通解法
(2)时间复杂度O(N)的解法

7.数组转换为树题目

 

你可能感兴趣的:(算法精讲学习笔记 队列和栈)