栈和队列
一、栈
1.栈的定义
栈是一种线性表,一种抽象数据类型,它只允许在一端进行插入或删除操作。又叫做LIFO(后进先出)线性表。
栈的基本操作有入栈push和出栈pop,栈顶top指的是进行操作的一端。如图,只有栈顶元素可以访问。进栈次序为a1、a2、a3、a4、a5,出栈次序为a5、a4、a3、a2、a1
2.栈的实现
栈是受限的线性表,因此任何实现表的方法都能实现栈,主要就是顺序栈和链栈。
2.1 顺序栈
使用数组存放栈的数据元素,设有一个头指针top执行栈顶,初始时为top=0,顺序栈的实现代码:
进栈:先放在top+1
public void push(T item){
if(top >= capacity) return;
items[top] = item;
top ++;
}
出栈:先top-1再取
public T pop(){
if(top < 0) return null;
return (T) items[--top];
}
2.2 链栈
通常采用单链表实现,所有的操作都在表头进行。栈节点为:
private class Node{
T item;
Node next;
}
链栈的实现代码,有一个头指针top,只能用top指针执行push、pop(插入删除)
进栈:头插法
public void push(T item){
Node old = top;
top = new Node();
top.item = item;
top.next = old;
count++;
}
出栈:取时只需把top节点指向下个节点即可
public T pop(){
T item = top.item;
top = top.next;
count--;
return item;
}
二、队列
1.队列
只在一端插入,另一端删除的线性表,类似于日常的排队,特性是先进先出FIFO。其中有两个指针,头指针head和尾指针tail,在tail插入,在head读取。
2.队列的实现
2.1 顺序存储
使用数组,初始状态时,head=tail=0;当tail==MaxSize时,并不能说明队列满了,当head指针为tail的前一个位置,此时队列中只有一个元素,但没满,这时入队出现上溢出,这时一种假溢出。
2.1.1 循环队列
也称环形队列,环形缓冲区,臆造一个环状的空间,当队头或队首指针达到最大时,重置为零,可以使用取余运算实现,(也能不用取余)。
取余运算:
初始时,head = tail = 0;
队首加1,head = (head + 1) % MaxSize;
队尾加1,tail = (tail + 1) % MaxSize;
队列长度,(tail + MaxSize - head) % MaxSize;
不使用取余:
以RingBuffer环形缓冲区为例,具体代码在GitHub,其中入队和出队的代码如下,没使用取模运算,(对计算机来说,加1减1比取模简单)
入队:
public boolean put(T item){
int next = tail + 1;
if(next >= bufferSize){
next = 0;
}
if(next == head){
lost++;
return false;
}
rBuffer[next] = item;
tail = next;
return true;
}
出队:
public T get(){
if(head == tail){
return null;
}
@SuppressWarnings("unchecked")
T item = (T) rBuffer[head];
rBuffer[head] = null;
if(++head >= bufferSize){
head = 0;
}
return item;
}
2.2 链式存储
链队列,使用一个带有队头head和队尾tail指针的单链表,在head读取,在tail插入。节点类型如下:
private Node head; // 队头
private Node tail; // 队尾
private class Node{ // 节点
T item;
Node next;
}
入队:
public void enqueue(T item){
Node old = tail;
tail = new Node();
tail.item = item;
tail.next = null;
if(isEmpty()){
head = tail;
} else {
old.next = tail;
}
count++;
}
出队:
public T dequeue(){
T res = head.item;
head = head.next;
if(isEmpty()){
tail = null;
}
count--;
return res;
}
源码地址:https://github.com/cyhe/algorithm/tree/master/src/algo/linearlist/stack