【数据结构】队列(顺序队列、链队列)的JAVA代码实现

队列(queue)是一种特殊的线性表,只允许在表的一端进行插入操作而在另一端进行删除的线性表。进行插入操作的端称为队尾,进行删除操作的一端称为队头。队列中没有数据元素时称为空队列。

队列的操作是按照先进先出(first in first out)或后进后出(last in last out)的原则进行的。因此,队列又被称为FIFO表。它的实现方式主要有顺序队列、链队列两种

 

队列的抽象数据模型

  1. 数据元素:可以为任意类型,只要同属于一种数据类型即可;
  2. 数据关系:数据元素之间呈线性关系;
  3. 数据操作:对队列的基本操作定义在IQueue中,代码如下:
public interface IQueue {
	boolean enqueue(E item); //入队列操作
    E dequeue(); //出队列操作
    E peek(); //取对头元素
    int size(); //求队列的长度
    boolean isEmpty(); //判断队列是否为空  
    boolean isFull(); //判断队列是否为满  
}

队列的实现方式

顺序队列

用一片连续的存储空间来存储队列中的数据元素,这样的队列称为顺序队列。类似于顺序栈,用一维数组来存放顺序队列中的数据元素。队头设置在最近一个已经离开队列的元素所占的位置,用front表示;队尾设置在最近一个进行入队列的元素位置,用rear表示。front和rear随着插入和删除而变化。当队列为空时,front=rear=-1。

当有数据元素入队列时,队尾指示器rear加1,当有数据元素出队列时,队头指示器front加1。当front=rear时,表示队列为空,当队尾指示器rear达到数组的上限处而front为-1时,队列为满。队尾指示器rear的值大于对头指示器front的值,队列中的元素个数可以由rear-front求得。

但是!有时候,队列未满但再有一个元素入队就会出现溢出。但事实上队列并未满,还有空闲空间,这种情况成为“假溢出”。这是由于队列“队尾入队,队头出”的操作原则造成的。解决假溢出的方法是将顺序队列看成是首尾相接的循环结构,首尾指示器的关系不变,这种队列叫循环顺序队列。

当队尾指示器rear达到数组的上限是,如果还有数据元素入队并且数组的第0个空间空闲时,队尾指示器rear指向数组的0端。所以,队尾指示器的加1操作修改为:rear=(rear+1)%maxsize

队头指示器的操作也是如此。当队头指示器front达到数组的上限时,如果还有数据元素出队,队头指示器指向数组的0端。所以,队头指示器的加1操作修改为:front=(front+1)%maxsize

这样又有一个问题,队满和队空的时候,都有rear=front。为了解决这个问题的方法是一般少用一个空间,所以判断队空的条件是rear=front,判断队满的条件是(rear+1)%maxsize=front,与此同时,循环队列中数据元素的个数是(rear-front+maxsize)%maxsize。此时,front表示队头,rear表示队尾,两者的范围都是0-maxsize-1。

public class SeqQueue implements IQueue {
	private int maxsize; //队列的容量
	private E[] data; // 存储循环顺序队列中的数据元素
	private int front; // 指示最近一个己经离开队列的元素所占的位置
	private int rear; // 指示最近一个进行入队列的元素的位置
    //初始化队列
	@SuppressWarnings("unchecked")
	public SeqQueue(Class type, int maxsize) {
		data = (E[]) Array.newInstance(type, maxsize);
		this.maxsize = maxsize;
		front = rear = -1;
	}
	//入队列操作
	public boolean enqueue(E item) {
		if (!isFull()) {
			rear = (rear + 1) % maxsize;
			data[rear] = item;
			return true;
		} else
			return false;
	}
	 //出队列操作
	public E dequeue() {
		if (!isEmpty()) {
			front = (front + 1) % maxsize;
			return data[front];
		} else
			return null;

	}
	
	//取对头元素
	public E peek() {
		if (!isEmpty()) {
			return data[(front + 1) % maxsize];
		} else
			return null;
	}
	//求队列的长度
	public int size() {

		return (rear - front + maxsize) % maxsize;
	}
	// 判断队列是否为空
	public boolean isEmpty() {
		if (front == rear) {
			return true;
		} else {
			return false;
		}
	}
	// 判断循环顺序队列是否为满
	public boolean isFull() {
		if ((front == -1 && rear == maxsize - 1)
				|| (rear + 1) % maxsize == front) {
			return true;
		} else {
			return false;
		}
	}
}

链队列

用链式存储结构来存储队列中的数据元素,这样的队列称为链队列。同链栈一样,链队列一般也采用单链表来表示,设队头指示器为front,队尾指示器rear。

class QueueNode
{
	private E data; // 数据域
	private QueueNode next; // 引用域
	 //构造函数
	public QueueNode(){}
	public QueueNode(E data) {
		this.data = data;	
	}
	public QueueNode(E data, QueueNode next) {
		this.data = data;
		this.next = next;
	}
	//数据域get属性
	public E getData() {
		return data;
	}
	//数据域set属性
	public void setData(E data) {
		this.data = data;
	}
	//引用域get属性
	public QueueNode getNext() {
		return next;
	}
	//引用域get属性
	public void setNext(QueueNode next) {
		this.next = next;
	}
}
public class LinkQueue implements IQueue {
	private QueueNode front; // 队列头指示器
	private QueueNode rear; // 队列尾指示器
	private int maxsize; // 队列的容量,假如为0,不限容量
	private int size; // 队列数据元素个数

	// 初始化链队列
	public LinkQueue() {
		front = rear = null;
		size = 0;
		maxsize = 0;
	}

	// 初始化限容量的链队列
	public LinkQueue(int maxsize) {
		super();
		this.maxsize = maxsize;
	}

	// 入队列操作
	public boolean enqueue(E item) {
		QueueNode newnode = new QueueNode(item);
		if (!isFull()) {
			if (isEmpty()) {
				front = newnode;
				rear = newnode;
			} else {
				rear.setNext(newnode);
				rear = newnode;
			}
			++size;
			return true;
		} else
			return false;
	}

	// 出队列操作
	public E dequeue() {
		if (isEmpty())
			return null;
		QueueNode node = front;
		front = front.getNext();
		if (front == null) {
			rear = null;
		}
		--size;
		return node.getData();

	}

	// 取对头元素
	public E peek() {
		if (!isEmpty()) {
			return front.getData();
		} else
			return null;
	}

	// 求队列的长度
	public int size() {
		// TODO Auto-generated method stub
		return size;
	}

	// 判断队列是否为空
	public boolean isEmpty() {
		if ((front == rear) && (size == 0)) {
			return true;
		} else {
			return false;
		}
	}

	// 判断队列是否为满
	public boolean isFull() {
		if (maxsize != 0 && size == maxsize) {
			return true;
		} else {
			return false;
		}
	}
}

 

总结与分析

  • 位于java.util.Queue的接口拓展了java.util.Collection接口,定义了队列存取元素的基本方法。

【数据结构】队列(顺序队列、链队列)的JAVA代码实现_第1张图片

 

你可能感兴趣的:(《数据结构》Java语言笔记)