目 录
1 队列
2 实现定容量队列(底层是数组)
3 实现定容量队列(底层是双向链表)
1 队列
队列是一种线性的数据结构。
它有两个主要的功能方法:一个是存入(put),一个是取出(take)。
存入就是把元素存入队列中。
取出就是从队列中拿走这个元素,拿走后队列中就不存在这个元素了。
队列的存入和取出受FIFO(先进先出)原则限制,即最先存入队列的元素一定最先被取出。
与此相对应的一种数据结构是栈,最先存入栈的元素一定最后被取出。
实现一个队列,底层可以用数组,也可以用链表。
下文将分别用数组和双向链表实现一个定容量的队列。设计如下方法:
(1)存入put(),取出take();
(2)返回队列中元素个数size();
(3)返回队列当前容量大小length();
(4)清空队列clear()。
2 实现定容量队列(底层是数组)
定义队列类MyQueue
定义属性:数组array、队列中元素个数int size、队列容量int capacity
private E[] array;
private int capacity;
private int size;
定义方法:
(1)构造方法
public MyQueue(int capacity) {
this.capacity = capacity;
this.array = (E[]) new Object[capacity];
this.size = 0;
}
(2)put方法
/**
*
* @param e 存入的元素
*/
public void put(E e){
// 判断队列是否已满,如果已满,不能添加元素
if(size == capacity){
throw new ArrayIndexOutOfBoundsException();
}
// 用下标体现存入元素的先后顺序,下表越大表示越晚存入
array[size] = e;
size++;
}
(3)take方法
/**
*
* @return 取出的元素
*/
public E take(){
// 判断队列是否为空,如果为空,不能取出元素
if (array != null){
// 先进先出,第0个位置存着最早存入的元素,应将其取出
E e = array[0];
// 剩余位置元素依次向前挪,下次还是从第0个位置取出
for (int i = 1; i < size; i++) {
array[i - 1] = array[i];
}
array[size] = null;
size--;
return e;
}
throw new ArrayIndexOutOfBoundsException();
}
(4)clear方法
这里不考虑在物理上删除原来的数组,而是暂时先用new关键字新建一个数组。
public void clear(){
this.array = (E[]) new Object[capacity];
this.size = 0;
}
(5)其他方法
public int size(){
return this.size;
}
public int length(){
return this.capacity;
}
public void setCapacity(int capacity){
this.capacity = capacity;
}
public double capacityRate(){
double capacity = this.capacity;
double size = this.size;
return size/capacity;
}
public String getArray(){
return Arrays.toString(this.array);
}
测试
写下面这段程序简单测试一下。
public class Main {
public static void main(String[] args) {
MyQueue<String> myQueue = new MyQueue<>(100);
for (int i = 0; i < 50; i++) {
myQueue.put("x");
System.out.println(myQueue.getArray());
System.out.println(myQueue.size());
System.out.println(myQueue.capacityRate());
}
for (int i = 0; i < 20; i++) {
myQueue.take();
System.out.println(myQueue.getArray());
System.out.println(myQueue.size());
System.out.println(myQueue.capacityRate());
}
myQueue.clear();
System.out.println(myQueue.getArray());
System.out.println(myQueue.size());
System.out.println(myQueue.capacityRate());
}
}
3 实现定容量队列(底层是双向链表)
定义结点类Node
定义属性:结点值value、下一结点next、上一结点front
private E value;
private Node<E> next;
private Node<E> front;
定义一系列getter、setter方法。
public Node(E value) {
this.value = value;
}
public void setNext(Node<E> next) {
this.next = next;
}
public Node<E> next() {
return this.next;
}
public void setFront(Node<E> front) {
this.front = front;
}
public Node<E> front() {
return this.front;
}
public E getValue() {
return value;
}
定义队列类MyQueue
定义属性:头结点head、尾结点last、队列中元素个数int size、队列容量int capacity
private Node<E> head;
private Node<E> last;
private int size;
private int capacity;
定义方法:
(1)构造方法
public MyQueue(int capacity) {
this.size = 0;
this.capacity = capacity;
}
(2)put方法
把要存入队列的元素装入结点,并放到双向链表的头部。
这样,头结点的元素永远是最后存入队列的元素。
/**
*
* @param e 存入的元素
*/
public void put(E e) {
// 判断队列是否已满
if (size == capacity){
throw new ArrayIndexOutOfBoundsException();
}
Node<E> newNode = new Node<>(e);
// 如果队列没有结点,把当前结点作为尾结点、头结点
// 如果队列有结点,将当前结点放到头结点的上方,并设置头结点为当前结点
if (size == 0) {
last = newNode;
} else {
newNode.setNext(head);
head.setFront(newNode);
}
head = newNode;
size++;
}
(3)take方法
/**
*
* @return 取出的元素
*/
public E take() {
// 判断队列是否为空
if (size == 0) {
throw new ArrayIndexOutOfBoundsException();
}
// 尾结点中的value永远是最先存入队列的,因此取出尾结点的value
E e = last.getValue();
// 将倒数第二个结点设置为尾结点
last.front().setNext(null);
last = last.front();
size--;
return e;
}
(4)clear方法
public void clear() {
this.size = 0;
this.head = null;
this.last = null;
// 中间的结点,物理上并未被删除,只是不能访问
}
(5)其他方法
public int size() {
return this.size;
}
public int length(){
return this.capacity;
}
public void setCapacity(int capacity){
this.capacity = capacity;
}
public double capacityRate(){
double capacity = this.capacity;
double size = this.size;
return size/capacity;
}
@Override
public String toString() {
String str = "";
Node<E> temp = head;
for (int i = 0; i < this.size; i++) {
str += temp.getValue().toString();
temp = temp.next();
}
return str;
}
测试
写下面这段程序简单测试一下。
public class Main {
public static void main(String[] args) {
MyQueue<String> myQueue = new MyQueue<>(100);
for (int i = 0; i < 50; i++) {
myQueue.put("x");
System.out.println(myQueue);
System.out.println(myQueue.size());
System.out.println(myQueue.capacityRate());
}
for (int i = 0; i < 20; i++) {
String taken = myQueue.take();
System.out.println(taken);
System.out.println(myQueue);
System.out.println(myQueue.size());
System.out.println(myQueue.capacityRate());
}
myQueue.clear();
System.out.println(myQueue);
System.out.println(myQueue.size());
System.out.println(myQueue.capacityRate());
}
}