队列
队列:允许在一端进行插入,在另一端进行删除。允许插入的一端称为队尾,允许删除的一端称为队头。顾名思义,队列需要两个变量来记录队尾和队首的位置,方便进行入队和出队操作。
队列的特点:先进先出
链队列
需要注意的是:出队前需要确定队列里面是否有元素,并且出队后要检查是否队列为空,如果为空,还需要重新赋值tailNode为headerNode,避免tailNode指向null,再次添加队列元素时报错。
package day07;
public class LinkedQueue {
class Node {
/**
* The data.
*/
int data;
/**
* The reference to the next node.
*/
Node nextNode;
/**
* The constructor.
*
* @param paraValue The data.
*/
public Node(int paraValue) {
data = paraValue;
nextNode = null;
}// Of the constructor
}// Of class Node
/**
* The header of the queue.
*/
Node headerNode;
/**
* The tail of the queue.
*/
Node tailNode;
/**
* Construct an empty sequential list.
*/
public LinkedQueue() {
headerNode = new Node(-1);
tailNode = headerNode;
}// Of the first constructor.
/**
* Enqueue.
*
* @param paraValue The value of the new code.
*/
public void enqueue(int paraValue) {
Node tempNode = new Node(paraValue);
tailNode.nextNode = tempNode;
tailNode = tempNode;
}// Of enqueue
public int dequeue() {
if (headerNode == tailNode) {
System.out.println("No element in the queue");
return -1;
} // Of if
int resultValue = headerNode.nextNode.data;
headerNode.nextNode = headerNode.nextNode.nextNode;
// The queue becomes empty.
if (headerNode.nextNode == null) {
tailNode = headerNode;
} // Of if
return resultValue;
}// Of dequeue
/**
* Overrides the method claimed in Object, the superclass of any class.
*/
public String toString() {
String resultString = "";
if (headerNode.nextNode == null) {
return "empty";
} // Of if
Node tempNode = headerNode.nextNode;
while (tempNode != null) {
resultString += tempNode.data + ", ";
tempNode = tempNode.nextNode;
} // Of while
return resultString;
}// Of toString
/**
* The entrance of the program.
*
* @param args Not used now.
*/
public static void main(String args[]) {
LinkedQueue tempQueue = new LinkedQueue();
System.out.println("Initialized, the list is: " + tempQueue.toString());
for (int i = 0; i < 5; i++) {
tempQueue.enqueue(i + 1);
} // Of for i
tempQueue.dequeue();
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
int tempValue;
for (int i = 0; i < 3; i++) {
tempValue = tempQueue.dequeue();
System.out.println("Looped delete " + tempValue + ", the queue is: " + tempQueue.toString());
} // Of for i
for (int i = 0; i < 3; i++) {
tempQueue.enqueue(i + 10);
} // Of for i
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
}// Of main
}// Of class LinkedQueue
运行结果:
循环队列
基于顺序存储的队列,可以提高内存空间的使用率,但为了区分队列为空和满,需要牺牲一个存储空间,当head==tail时,表示为空,(tail+1)%MAX_SPACE==head时,表示队列为满。
int类型的循环队列:
package day07;
public class CircleIntQueue {
/**
* The total space. One space can never be used.
*/
public static final int TOTAL_SPACE = 10;
/**
* The data.
*/
int[] data;
/**
* The index for calculation the head. The actual head is head % TOTAL_SPACE.
*/
int head;
/**
* The index for calculating the tail.
*/
int tail;
public CircleIntQueue() {
data = new int[TOTAL_SPACE];
head = 0;
tail = 0;
}// Of the first constructor
/**
* Enqueue.
*
* @param paraValue The value of the new node.
*/
public void enqueue(int paraValue) {
if ((tail + 1) % TOTAL_SPACE == head) {
System.out.println("Queue full.");
return;
} // Of if
data[tail % TOTAL_SPACE] = paraValue;
tail++;
}// Of enqueue;
/**
* Dequeue.
*
* @return The value at the head.
*/
public int dequeue() {
if (head == tail) {
System.out.println("No element in the queue");
return -1;
} // Of if
int resultValue = data[head % TOTAL_SPACE];
head++;
return resultValue;
}// Of dequeue
/**
* Overrides the method claimed in Object, the superclass of any class.
*/
public String toString() {
String resultString = "";
if (head == tail) {
return "empty";
} // Of if
for (int i = head; i < tail - 1; i++) {
resultString += data[i % TOTAL_SPACE] + ", ";
} // Of for i
resultString += data[(tail - 1) % TOTAL_SPACE];
return resultString;
}// Of toString
/**
* The entrance of the program.
*
* @param args Not used now.
*/
public static void main(String args[]) {
CircleIntQueue tempQueue = new CircleIntQueue();
System.out.println("Initialized, the list is: " + tempQueue.toString());
for (int i = 0; i < 5; i++) {
tempQueue.enqueue(i + 1);
} // Of for i
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
int tempValue = tempQueue.dequeue();
System.out.println("Dequeue " + tempValue + ", the queue is: " + tempQueue.toString());
for (int i = 0; i < 6; i++) {
tempQueue.enqueue(i + 10);
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
} // Of for i
for (int i = 0; i < 3; i++) {
tempValue = tempQueue.dequeue();
System.out.println("Dequeue " + tempValue + ", the queue is: " + tempQueue.toString());
} // Of for i
for (int i = 0; i < 6; i++) {
tempQueue.enqueue(i + 100);
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
} // Of for i
}// Of main
}// Of class
运行结果:
char类型的循环队列:
package day07;
public class CircleIntQueue {
/**
* The total space. One space can never be used.
*/
public static final int TOTAL_SPACE = 10;
/**
* The data.
*/
char[] data;
/**
* The index for calculation the head. The actual head is head % TOTAL_SPACE.
*/
int head;
/**
* The index for calculating the tail.
*/
int tail;
public CircleIntQueue() {
data = new char[TOTAL_SPACE];
head = 0;
tail = 0;
}// Of the first constructor
/**
* Enqueue.
*
* @param paraValue The value of the new node.
*/
public void enqueue(char paraValue) {
if ((tail + 1) % TOTAL_SPACE == head) {
System.out.println("Queue full.");
return;
} // Of if
data[tail % TOTAL_SPACE] = paraValue;
tail++;
}// Of enqueue;
/**
* Dequeue.
*
* @return The value at the head.
*/
public char dequeue() {
if (head == tail) {
System.out.println("No element in the queue");
return '\0';
} // Of if
char resultValue = data[head % TOTAL_SPACE];
head++;
return resultValue;
}// Of dequeue
/**
* Overrides the method claimed in Object, the superclass of any class.
*/
public String toString() {
String resultString = "";
if (head == tail) {
return "empty";
} // Of if
for (int i = head; i < tail - 1; i++) {
resultString += data[i % TOTAL_SPACE] + ", ";
} // Of for i
resultString += data[(tail - 1) % TOTAL_SPACE];
return resultString;
}// Of toString
/**
* The entrance of the program.
*
* @param args Not used now.
*/
public static void main(String args[]) {
CircleIntQueue tempQueue = new CircleIntQueue();
System.out.println("Initialized, the list is: " + tempQueue.toString());
for (char i = '0'; i < '5'; i++) {
tempQueue.enqueue(i);
} // Of for i
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
char tempValue = tempQueue.dequeue();
System.out.println("Dequeue " + tempValue + ", the queue is: " + tempQueue.toString());
for (char i = 'a'; i < 'f'; i++) {
tempQueue.enqueue(i);
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
} // Of for i
for (int i = 0; i < 3; i++) {
tempValue = tempQueue.dequeue();
System.out.println("Dequeue " + tempValue + ", the queue is: " + tempQueue.toString());
} // Of for i
for (char i = 'A'; i < 'F'; i++) {
tempQueue.enqueue(i);
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
} // Of for i
}// Of main
}// Of class
运行结果:
通过上面两段代码,不难发现重复的代码部分有很多,如果在C语言中,可以使用typedef将不同data类型的CircleIntQueue定义为同一个类,但无奈Java中没有这样的功能。现在我能想到的办法是,在CircleIntQueue的构造函数中设置参数,根据调用者new 一个CircleIntQueue对象时传递的参数来初始化data数据,并把类型保存为实例属性,至于有关类型的方法调用,则通过方法重载实现。