一、仿写代码
在循环队列中,当队列为空,可知 front=rear;而当所有队列空间全占满时,也有 front=rear。为了区别这两种情况,假设队列使用的数组有 k 个存储空间,size表示队头到队尾的长度,如果size==k则表示队列已满。根据以上可知,队列判空的条件是 front=rear,而队列判满的条件是 size == k。
对于一个固定大小的数组,只要知道队尾rear 与队首 front,即可计算出队列当前的长度:
(rear−front+k) mod k
循环队列的属性如下:
- elements:一个固定大小的数组,用于保存循环队列的元素。
- k:循环队列的容量,即队列中最多可以容纳的元素数量。
- front:队列首元素对应的数组的索引。
- rear:队列尾元素对应的索引的下一个索引。
循环队列的接口方法如下:
- MyCircularQueue(int k): 初始化队列,同时base 数组的空间初始化大小为 k。front,rear 全部初始化为 0。
- isEmpty():检测队列是否为空,根据之前的定义只需判断 rear 是否等于front。
- isFull():检测队列是否已满,根据之前的定义只需判断 size 是否等于 k。
- enQueue(int value):在队列的尾部插入一个元素,并同时将队尾的索引 rear 更新为 (rear+1) mod k。
- deQueue():从队首取出一个元素,并同时将队首的索 front 更新为 (front+1) mod k。
- Front():返回队首的元素,需要检测队列是否为空。
- Rear():返回队尾的元素,需要检测队列是否为空。
- showQueue():输出队列所有数据
数组法:
class MyCircularQueue {
private int front;
private int rear;
private int size;
private int k;
private int[] elements;
public static void main(String[] args) {
MyCircularQueue myCircular = new MyCircularQueue(5);
myCircular.enQueue(3);
myCircular.enQueue(6);
myCircular.enQueue(5);
myCircular.deQueue();
int a = myCircular.Front();
int b = myCircular.Rear();
System.out.println(a);
System.out.println(b);
myCircular.showQueue();
}
// 构造器
public MyCircularQueue(int k) {
this.k = k;
elements = new int[k];
rear = front = 0;
}
// 判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
// 判断队列是否已满
public boolean isFull() {
return size == k;
}
// 在队列尾部插入一个元素
public boolean enQueue(int value) {
if(isFull()) {
return false;
}
elements[rear] = value;
rear = (rear + 1)%k;
size++;
return true;
}
// 从队列头部删除一个元素
public boolean deQueue() {
if(isEmpty()) {
return false;
}
front = (front + 1)%k;
size--;
return true;
}
// 返回头部元素
public int Front() {
if(isEmpty()) {
return -1;
}
return elements[front];
}
// 返回尾部元素
public int Rear() {
if(isEmpty()) {
return -1;
}
return elements[(rear-1)%k];
}
// 显示队列所有数据
public void showQueue() {
if(isEmpty()) {
System.out.println("队列为空,没有值~");
}
for(int i = front; i<rear; i++) {
System.out.println(elements[i]);
}
}
}
链表法:
class MyCircularQueue{
private int k,count;
public static void main(String[] args) {
MyCircularQueue myCircularQueue = new MyCircularQueue();
myCircularQueue.Rear(3);
myCircularQueue.Rear(5);
myCircularQueue.Rear(6);
myCircularQueue.poll(); // 删除
int a = myCircularQueue.peek(); // 返回队头
myCircularQueue.poll();
int b = myCircularQueue.poll();
int c = myCircularQueue.peek();
int d = myCircularQueue.size(); // 返回队列长度
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
public static class Node{
public int val;
public Node next;
public Node(int val, Node next) {
this.val = val;
this.next = next;
}
public Node(int val) {
this.val = val;
}
}
public Node head;
public Node last;
// 尾部插入
public void Rear(int val) {
if(head == null) {
head = new Node(val);
last = head;
}else {
Node cur = new Node(val);
last.next = cur;
last = cur;
}
}
// 从头部删除元素,并返回删除的数
public int poll() {
if(head == null || last == null) {
return -1;
}
int val = head.val;
head = head.next;
return val;
}
// 返回头部元素,但不删除
public int peek() {
if(head == null || last == null) {
return -1;
}
int val = head.val;
return val;
}
// 队列长度
public int size() {
Node cur = head;
int size = 0;
while(cur!=null) {
cur=cur.next;
size++;
}
return size;
}
}
二、算法题巩固
(1)用两个队列实现栈
类定义:
- Queue类表示生成队列
- Stack类表示生成栈
属性定义和方法定义看代码注释
// 创建队列
class Queue {
private int front;
private int rear;
private int size;
private int k;
private int[] elements;
// 构造器
public Queue(int k) {
this.k = k;
elements = new int[k];
rear = front = 0;
}
// 判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
// 判断队列是否已满
public boolean isFull() {
return size == k;
}
// 在队列尾部插入一个元素
public boolean offer(int value) {
if(isFull()) {
return false;
}
elements[rear] = value;
rear = (rear + 1)%k;
size++;
return true;
}
// 从队列头部删除一个元素
public int poll() {
if(isEmpty()) {
return -1;
}
int val = elements[front];
front = (front + 1)%k;
size--;
return val;
}
// 返回头部元素
public int peek() {
if(isEmpty()) {
return -1;
}
return elements[front];
}
// 返回尾部元素
public int Rear() {
if(isEmpty()) {
return -1;
}
return elements[(rear-1)%k];
}
// 显示队列所有数据
public void showQueue() {
if(isEmpty()) {
System.out.println("队列为空,没有值~");
}
for(int i = front; i<rear; i++) {
System.out.println(elements[i]);
}
}
}
public class Stack {
public static void main(String[] args) {
Stack stack = new Stack();
stack.push(1);
stack.push(2);
int a = stack.top(); // 返回栈顶元素
stack.pop(); // 删除并返回栈顶元素
int b = stack.pop();
System.out.println(a);
System.out.println(b);
System.out.print(stack.empty());
}
// 创建两个长度为5的队列对象
Queue m1;
Queue m2;
public Stack() {
m1 = new Queue(5);
m2 = new Queue(5);
}
// 向栈中添加元素
public void push(int val) {
m2.offer(val);
while(!m1.isEmpty()) {
m2.offer(m1.poll());
}
Queue temp = m1;
m1 = m2;
m2 = temp;
}
// 移除并返回栈顶元素
public int pop() {
return m1.poll();
}
// 返回栈顶元素
public int top() {
return m1.peek();
}
// 判断栈是否为空
public boolean empty() {
return m1.isEmpty();
}
}
(2)用单队列实现栈
public class Stack {
public static void main(String[] args) {
Stack stack = new Stack();
stack.push(1);
stack.push(2);
int a = stack.top(); // 返回栈顶元素
stack.pop(); // 删除并返回栈顶元素
int b = stack.pop();
System.out.println(a);
System.out.println(b);
System.out.print(stack.empty());
}
// 创建两个长度为5的队列对象
Queue m1;
public Stack() {
m1 = new Queue(5);
}
// 向栈中添加元素
public void push(int val) {
int n = m1.Size();
m1.offer(val);
// 单个队列实现栈
for(int i = 0; i < n; i++) {
m1.offer(m1.poll());
}
}
// 移除并返回栈顶元素
public int pop() {
return m1.poll();
}
// 返回栈顶元素
public int top() {
return m1.peek();
}
// 判断栈是否为空
public boolean empty() {
return m1.isEmpty();
}
}