链队列
队列的链式存储结构,其实就是线性表的单链表,只不过他只能尾进头出而已,我们把它称为链队列.
为了操作方便,我们将队头指向链队列的头结点,空队列时,front
和rear
都指向头结点
- 整个感觉和单链表差不多,就是多了两个变量,比较简单,就过多叙述了
代码
package ***;
/**
* @Author: wsh
*/
public class LinkQueueTest {
public static void main(String[] args) {
LinkQueueManager linkQueueManager = new LinkQueueManager();
String data = "31,21,17,16";
linkQueueManager.init(data.split(","));
linkQueueManager.out("初始化");
linkQueueManager.put(10);
linkQueueManager.out("添加10");
for (int i = 0; i < 6; i++) {
System.out.println(i+1+"次取出 "+linkQueueManager.get());
}
linkQueueManager.out("最后输出");
linkQueueManager.put(10);
linkQueueManager.out("添加10");
}
}
class LinkQueueManager{
QNode qNode = new QNode();
//为了取出时 O(1)
QNode front;//头
QNode rear;//尾
public Integer get() {
if (front == rear) {
System.out.println("队列空了,失败");
return -1;
}
Integer data = front.nextNode.data;
//到达队尾 rear也指向头结点
if (front.nextNode == rear) {
rear = front;
}
front.nextNode = front.nextNode.nextNode;
return data;
}
public void put(int value) {
QNode node = new QNode();
node.data=value;
rear.nextNode = node;
rear = node;
}
/**
* 这里很显然得用尾插法来初始化
*/
public void init(String [] data) {
//声明头节点
qNode.data=null;
qNode.nextNode=null;
front=qNode;
rear = qNode;
//设置变量 始终指向队尾
QNode q = qNode;
for (String datum : data) {
int i = Integer.parseInt(datum);
QNode node = new QNode();
node.data=i;
q.nextNode = node;
q = node;
//设置尾变量
rear=node;
}
}
public void out(String str) {
System.out.println(str);
//头结点不要输出
QNode q = qNode.nextNode;
while (q != null) {
System.out.print(q.data+" ");
q = q.nextNode;
}
System.out.println("\n=====front:"+front.data+" rear:"+rear.data);
}
}
class QNode{
Integer data;
QNode nextNode;
}
收获
- 一开始我想为啥还声明两个变量
front
和rear
来指向头尾,难道链表自己不就能判断出来么.在使用中发现非常有必要:
- 入队列时间复杂度O(1),但是没有
rear
指向未队列的话,取出最后一个时间复杂度就需要O(n),因为一个个遍历到最最最后面呀 - 在判断空队列时,若有两个变量铺垫,将很好先进行判断,排查异常比较方便(好吧,这个比较勉强)
- 初始化得用尾插法了,比较是队列,注意方式
章节总结
注意是章节总结,这一章讲的是栈和队列,它们都是特殊的线性表,只不过对插入和删除操作做了限制.
- 栈(Stack)是限定仅在表尾进行插入和删除操作的线性表
- 队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表
它们均可以用线性表的顺序存储结构来实现,但都存在着顺序存储的一些弊端,因此它们各自有各自的技巧来解决这个问题.
- 对于栈来说,如果是两个相对数据类型的栈,则可以用数组的两端作栈底的方法来让两个栈共享数据,这就避免了最大化地利用数组的空间(好吧,我这个数组的共享栈代码没有敲)
- 对于队列来说,为了避免数组插入和删除时需要移动数据,于是就引入了循环队列,使得队头和队尾再数组中循环变化.解决了移动数据的时间损耗,使得本来插入和删除都是O(n)的时间复杂度变成O(1).
它们也都是可以通过链式存储结构来实现,实现原则上与线性表基本相同