目录

队列
队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表,一种先进先出的数据结构。
队尾:允许插入的一端。
队头:允许删除的一端。
队列的模拟实现
队列的底层可以是顺序表,可以是链表实现。
队列的链式实现
在实现队列前我们先思考使用什么样的链表来实现?
由于栈的特性是先入先出,如果使用单链表和双向链表都可以,
只要在单链表标记一下尾节点就行,
但是因为java提供的是双向链表实现的,所以我们使用双向链表。
接口实现
实现的接口如下:
public class myqueue {
//入队列
public void offer(int val) {}
//出队列
public int poll() {}
//获取队头元素 但是不删除
public int peek() { }
//判空
public boolean isempty() { }
//获取队列元素个数
public int size(){}
}
内部类
跟双向链表的内部类实现差不多。
static class listnode{
public int val;
public listnode prev;
public listnode next;
public listnode(int val) {
this.val = val;
}
}
public listnode head;
public listnode last;
入队列
实现思路:
- 先看队列是否为空,为空,头尾指向入队节点。
- 不为空尾节点的后继next指向入队节点,入队节点前驱prev指向尾节点,尾节点变为入队节点。
public void offer(int val){
listnode cur = new listnode(val);
if(isempty()){
head = last = cur;
return;
}
last.next = newnode;
newnode.prev = last;
last = newnode;
}
出队列
实现思路:
- 先判断队列是否为空,队列为空抛异常。
- 队列不为空,将头节点记录下来,头节点后一个节点前驱prev置为空,头节点变为后一个节点。
public int poll() throws nullpointerexception{
try{
if(isempty()){
throw new nullpointerexception;
}
}catch(nullpointerexception e){
e.printstacktrace();
}
listnode cur = head;
head.next.prev = null;
head = head.next;
return cur.val;
}
获取队头元素 但是不删除
实现思路:
- 先判断队列是否为空,队列为空抛异常。
- 队列不为空,返回头节点。
public int peek() throws nullpointerexception{
try{
if(isempty()){
throw new nullpointerexception;
}
}catch(nullpointerexception e){
e.printstacktrace();
}
return head.val;
}
判空
直接返回头是否为空就行。
public boolean isempty(){
return head == null;
}
获取队列元素个数
直接循环遍历即可。
public int size(){
listnode cur = head;
int size = 0;
while(cur != null){
cur = cur.next;
size++;
}
return size;
}
队列的顺序实现(循环队列)
直接使用顺序表的缺陷
当我们直接使用顺序表来放数据时,我们将元素入队列放在数组尾,出队列时将数组前面元素出去后,会使前面浪费的空间越来越大。
基于此我们就用循环队列来实现,还是数组作为底层,但我们将其想象成一个圆。
接口实现
class mycircularqueue {
//构造器,设置队列长度为 k
public mycircularqueue(int k) {}
// 向循环队列插入一个元素。如果成功插入则返回真。
public boolean enqueue(int value) {}
//从循环队列中删除一个元素。如果成功删除则返回真。
public boolean dequeue() {}
//从队首获取元素。如果队列为空,返回 -1
public int front() {}
//获取队尾元素。如果队列为空,返回 -1 。
public int rear() {}
//检查循环队列是否为空。
public boolean isempty() {}
//检查循环队列是否已满。
public boolean isfull() {}
};
成员变量
数组arr ,头下标front,尾节点下一个下标rear,数组长度size。
private int []arr;
private int front;
private int rear;
private int size;
构造器,设置队列长度为 k
因为我们使用的判空方法(下文讲)会造成一个空间的浪费,所以多申请一个空间。
public mycircularqueue(int k) {
size = k+1;
arr = new int[size];
front = rear = 0;
}
向循环队列插入一个元素 成功插入则返回真
实现思路:
- 判断队列是否已满,满了就返回false。
- 不满就在rear放。
- 因为是循环队列,所以rear的赋值要使用取余。
public boolean enqueue(int value) {
if(isfull()){
return false;
}else{
arr[rear] = value;
rear = (rear + 1) % size;
return true;
}
}
从循环队列中删除一个元素 成功删除则返回真
实现思路:
- 判断队列是否为空,空就返回false。
- 不空就直接将front指向下一个位置。
- 因为是循环队列,所以front的赋值要使用取余。
public boolean dequeue() {
if(isempty()){
return false;
}else{
front = (front + 1) % size;
return true;
}
}
从队首获取元素。如果队列为空,返回 -1
实现思路:
- 先判断队列是否为空,为空返回-1。
- 不为空,返回front下标对应值。
public int front() {
if(isempty()){
return -1;
}else{
return arr[front];
}
}
获取队尾元素。如果队列为空,返回 -1
实现思路:
- 先判断队列是否为空,为空返回-1。
- 不为空,再判断rear是否为0,是0就返回数组最后一个元素。
- 不为0,就直接返回rear-1下标对应的元素。
public int rear() {
if(isempty()){
return -1;
}else{
if(rear == 0){
return arr[size - 1];
}else{
return arr[rear - 1];
}
}
}
检查循环队列是否为空
检查空根据循环队列的实现有两种方法:
- 使用usedsize记录队列元素个数,个数为0就是空。
- 空一个空间,如果front和rear相等那就是空。
public boolean isempty() {
return rear == front;
}
检查循环队列是否已满
检查满根据循环队列的实现有两种方法:
- 使用usedsize记录队列元素个数,个数和size相等就是满。
- 空一个空间,如果rear的下一个位置就是front那就是满。
public boolean isfull() {
return front == (rear+1) % size;
}
java中的queue
java中queue的底层是linkedlist实现的。
并且queue只是一个接口,必须new对象linkedlist才能使用。
实现的接口
实现的接口如下:
常用方法
常用方法如下:
发表评论