4.栈和队列
栈(stack),是仅限定在表尾进行插入和删除操作的线性表 (一种特殊的线性表,有前驱后继关系)
我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何元素的称为空栈,栈又称为先进后出的线性表简称LIFO结构
先进后出,后进先出,最先进栈的元素不一定最后出,因为栈对元素的删除和增加位置有了限制,可时间没限制
例子:1,2,3依次放入栈中,可能是 1进 1出 2进 2出 3进,3出 所以进栈顺序是123出栈顺序也是123,其他情况相似。但是一定不会有312出栈顺序(自己想为什么,很重要!)
栈的顺序存储结构
既然栈是线性表的特例,那么栈的顺序存储结构其实也是线性表存储结构的简化。我们叫他线性栈(可用数组实现,下标0为栈底,定义一个指向最上元素的指针)
两栈共享,一个栈满溢出,一个栈没用完,两栈合成一个数组,两个栈底分别做数组的头尾,向中间靠拢,用得少,缺点明显,适合此消彼长的情况。
栈的链式存储结构
简称,链栈
如果栈在使用过程中元素变化不可预料,时大时小,推荐用链栈,变化在可控范围内用顺序栈。
栈的应用----递归,我们把一个直接或间接调用自身的函数,叫递归函数
写递归最怕陷入无穷的循环中,所以每个递归函数都要有至少一个跳出递归的条件
栈的应用----逆波兰表达式,数学表达式计算机无法根据运算规则运算,所以发明了计算机可以用来运算的数学表达式表达方法,也叫后缀表达法
例:9+(3-1)*3+10/2 ; 用后缀表达法写 9 3 1 - 3 * + 10 2 / + ; 根据运算顺序,一次把运算符号放在数字后面
计算机计算后缀式,将后缀表达式从左至右压入栈,先压入数字 931,再压入运算符“-”号,此时将13出栈进行减法操作再入站,以此类推(不详细说了)
队列,只允许在一端进行插入操作,另一端进行删除操作的线性表。
队列是一种先进先出(first in first out)的线性表,简称FIFO,允许插入的一端称为队尾,允许删除的一端称为队头。(像小学生站一排)
线性表有顺序和链式两种存储方式,栈作为特殊的线性表也有相应的链式和顺序存储方式,队列也是线性表,所以也有链式和顺序两种存储方式
队列的顺序存储结构,与线性表一样,在数组下标为0的地方是队头,依次在后面追加元素,这时时间复杂度是O(1),但是如果删掉队头,就必须把后面的前移,让0处有头,所以此时时间复杂度为O(n)
即使在队头队尾用上指针,由于数组大小是初始化就决定的,是固定的,所以或出现 溢出 错误,所以,为了解决这个问题,我们把队列头尾相接,这种顺序的存储结构叫循环队列
怎样计算队列有没有满,计算队列长度公式:(rear - front + QueueSize) % QueueSize
队列的链式存储结构,其实就是线性表的单链表,只不过只能头删除,尾插入,简称链队列。(比单链表操作简单,毕竟只需要考虑头尾的操作)
对比链队列和循环队列,基本操作的时间复杂度都是O(1),不对循环队列先申请好空间,使用期间不释放,而链队列每次申请和释放节点也需要时间,如果出入队频繁,两者还是有细微差别
对于空间来说,循环队列创建固定空间,容易造成浪费和溢出,链队列不存在这个问题,虽然指针也会占用一点空间,不过相对循环队列更灵活。两者根据情况选择
总结,栈和队列都是特殊的线性表,只是在插入和删除上做了限制。
--------------栈------------------------------队列------------
--顺序栈--共享栈--栈链------顺序队列--循环队列--链队列--