一、前言
栈和队列是两种很重要的线性结构,从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表。
二、栈
1、栈的概念
栈是限定仅在表尾进行插入或删除操作的线性表,因此对于栈来说,表尾有其特殊含义,称为栈顶,相应的,表头端称为栈底,不含元素的空表称为空栈。
假设栈S = (a1, a2, …, an),则称a1为栈底元素,an为栈顶元素。栈中元素按照a1,a2, …, an的顺序依次进展,退栈的第一个元素应为栈顶元素。栈的修改是按照后进先出的原则进行的,因此,栈又称为后进先出(last in first out)的线性表,简称LIFO结构,如下图所示:
栈的示意图
铁路调度站表示栈
2、栈的实现——Stack类源码解读(JDK1.8)
public class Stack<E> extends Vector<E> {
// 构造方法
public Stack() {}
// 入栈,返回入栈对象
public E push(E item) {
addElement(item);
return item;
}
// 出栈,此方法是线程安全的,返回出栈对象
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
// 查看栈顶元素,不会删除元素,线程安全的
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
// 判空
public boolean empty() {
return size() == 0;
}
// 查询一个元素在堆栈中的位置
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
}
三、队列
1、队列概念
和栈相反,队列是一种先进先出(first in first out,缩写为FIFO)的线性表,它只允许在表的一端进行插入,而在另一端删除元素。在队列中,最早进入队列的元素最早离开,允许插入的一端称为队尾,允许删除的一端称为队头。
2、双端队列
双端队列是限定插入和删除操作在表的两端进行的线性表,在实际使用中还可以有输出受限的双端队列(即一个端点允许插入和删除,另一个端点只允许删除)和输入受限的队列(即一个端点允许插入和删除,另一个端点只允许插入的双端队列)。
3、链队列
链队列,顾名思义,就是用链表表示的队列,和线性表一样,链队列也会有两个分别指向队头和队尾的指针(分别称为头指针和尾指针),如下图所示:
4、循环队列
为充分利用向量空间,克服假溢出现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列。循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列,如下图所示:
四、总结
- 栈和队列其实是一种操作受限的线性表;
- 栈的特点是LIFO,即后进先出;
- 队列的特点是FIFO,即先进先出;
- 队列只允许在一端插入,在另一端删除;