一种"操作受限"的线性表数据结构--队列(Queue)
队列(Queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。是一种先进先出(First In First Out)的线性表。支持两个基本操作:入队enqueue()和出队dequeue()。
队列的顺序存储结构--顺序队列(Array实现)
// 用数组实现的队列
public class ArrayQueue {
// 数组:items,数组大小:n
private String[] items;
private int n = 0;
// head 表示队头下标,tail 表示队尾下标
private int head = 0;
private int tail = 0;
// 申请一个大小为 capacity 的数组
public ArrayQueue(int capacity) {
items = new String[capacity];
n = capacity;
}
// 入队
public boolean enqueue(String item) {
// 如果 tail == n 表示队列已经满了
if (tail == n) return false;
items[tail] = item;
++tail;
return true;
}
// 出队
public String dequeue() {
// 如果 head == tail 表示队列为空
if (head == tail) return null;
// 为了让其他语言的同学看的更加明确,把 -- 操作放到单独一行来写了
String ret = items[head];
++head;
return ret;
}
}
队列需要两个指针:一个是head指针指向对头,一个是tail指针指向对尾。当不停的进行入队,出队操作时,会导致即使数组中还有空闲空间,也无法继续往队列中添加数据了。所以当队列的tail指针移动带数组的最后,如果有新的数据入队时,可以将head到tail之间的数据,整体进行数据搬移操作,整体将head-tail的数据搬移到0的位置。
循环队列
在普通的线性队列的实现中,当入队、出队频繁操作时,会出现数据搬移操作,导致在入队操作时,时入队的时间复杂度退化成O(n)。所以可以通过把队列的头尾相接的办法将顺序存储结构进阶成循环队列。
循环列队是把收尾相连,形成一个环。通过两个指针,指向头的front指针和指向尾的tail指针。当队列入队出队操作到数组的尾部时,将tail指针指向数组下标0的位置,继续入队出队操作。
循环队列最关键的是,如何确定队空和队满的条件。即
判断队空
tail=head
判断对满
(tail+1) % QueueSize = head
计算队列长度
(tail - front + QueueSize) % QueueSize
代码实现
public class CircularQueue {
// 数组:items,数组大小:n
private String[] items;
private int n = 0;
// head 表示队头下标,tail 表示队尾下标
private int head = 0;
private int tail = 0;
// 申请一个大小为 capacity 的数组
public CircularQueue(int capacity) {
items = new String[capacity];
n = capacity;
}
// 入队
public boolean enqueue(String item) {
// 队列满了
if ((tail + 1) % n == head) return false;
items[tail] = item;
tail = (tail + 1) % n;
return true;
}
// 出队
public String dequeue() {
// 如果 head == tail 表示队列为空
if (head == tail) return null;
String ret = items[head];
head = (head + 1) % n;
return ret;
}
}
循环列队必须有一个固定的长度,所以就有了存储元素和空间浪费问题。
队列的链式存储结构--链式队列
队列的链式存储结构,其实就是线性表的单链表,只不过他只能尾进头出。
网友评论