【数据结构】队列(顺序队列、链队列)的JAVA代码实现
2018-03-28 20:35
671 查看
队列(queue)是一种特殊的线性表,只允许在表的一端进行插入操作而在另一端进行删除的线性表。进行插入操作的端称为队尾,进行删除操作的一端称为队头。队列中没有数据元素时称为空队列。
队列的操作是按照先进先出(first in first out)或后进后出(last in last out)的原则进行的。因此,队列又被称为FIFO表。它的实现方式主要有顺序队列、链队列两种。
数据关系:数据元素之间呈线性关系;
数据操作:对队列的基本操作定义在IQueue中,代码如下:
用一片连续的存储空间来存储队列中的数据元素,这样的队列称为顺序队列。类似于顺序栈,用一维数组来存放顺序队列中的数据元素。队头设置在最近一个已经离开队列的元素所占的位置,用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<E> implements IQueue<E> {
private int maxsize; //队列的容量
private E[] data; // 存储循环顺序队列中的数据元素
private int front; // 指示最近一个己经离开队列的元素所占的位置
private int rear; // 指示最近一个进行入队列的元素的位置
//初始化队列
@SuppressWarnings("unchecked")
public SeqQueue(Class<E> 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;
}
}
}
{
private E data; // 数据域
private QueueNode<E> next; // 引用域
//构造函数
public QueueNode(){}
public QueueNode(E data) {
this.data = data;
}
public QueueNode(E data, QueueNode<E> 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<E> getNext() {
return next;
}
//引用域get属性
public void setNext(QueueNode<E> next) {
this.next = next;
}
}
队列的操作是按照先进先出(first in first out)或后进后出(last in last out)的原则进行的。因此,队列又被称为FIFO表。它的实现方式主要有顺序队列、链队列两种。
队列的抽象数据模型
数据元素:可以为任意类型,只要同属于一种数据类型即可;数据关系:数据元素之间呈线性关系;
数据操作:对队列的基本操作定义在IQueue中,代码如下:
public interface IQueue<E> { boolean enqueue(E item); //入队列操作 E dequeue(); //出队列操作 E peek(); //取对头元素 int size(); //求队列的长度 boolean isEmpty(); //判断队列是否为空 boolean isFull(); //判断队列是否为满 }
顺序队列
4000用一片连续的存储空间来存储队列中的数据元素,这样的队列称为顺序队列。类似于顺序栈,用一维数组来存放顺序队列中的数据元素。队头设置在最近一个已经离开队列的元素所占的位置,用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<E> implements IQueue<E> {
private int maxsize; //队列的容量
private E[] data; // 存储循环顺序队列中的数据元素
private int front; // 指示最近一个己经离开队列的元素所占的位置
private int rear; // 指示最近一个进行入队列的元素的位置
//初始化队列
@SuppressWarnings("unchecked")
public SeqQueue(Class<E> 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<E>{
private E data; // 数据域
private QueueNode<E> next; // 引用域
//构造函数
public QueueNode(){}
public QueueNode(E data) {
this.data = data;
}
public QueueNode(E data, QueueNode<E> 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<E> getNext() {
return next;
}
//引用域get属性
public void setNext(QueueNode<E> next) {
this.next = next;
}
}
public class LinkQueue<E> implements IQueue<E> { private QueueNode<E> front; // 队列头指示器 private QueueNode<E> 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<E> newnode = new QueueNode<E>(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<E> 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代码实现
- 【数据结构】堆栈(顺序栈、链栈)的JAVA代码实现
- 数据结构Java实现——②队列--->队列的“奇葩”一循环顺序队列
- 数据结构专题——栈与队列之顺序栈及其Java实现
- java实现队列数据结构代码详解
- 数据结构学习----顺序循环队列(Java实现)
- 数据结构Java实现07----队列:顺序队列&顺序循环队列、链式队列、顺序优先队列
- 数据结构Java实现07----队列:顺序队列&顺序循环队列、链式队列、顺序优先队列
- 数据结构Java实现07----队列:顺序队列&顺序循环队列、链式队列、顺序优先队列
- 数据结构Java实现07----队列:顺序队列&顺序循环队列、链式队列、顺序优先队列
- 请实现一个队列,既可以存放整数,又可以存放字符串。简单的说,队列是一种数据结构,按照先进先出的顺序管理进、出队列的元素
- C++类模板 实现队列的链式存储结构算法 《数据结构》(北京科海) 部分代码摘抄,自己编写运行
- 数据结构 --静态队列的一个简单的C语言代码实现
- 数据结构 - 队列简介 及 1个简单的c语言链式队列代码实现
- 【数据结构】之队列的java实现(一)
- Java,数据结构,线性表,顺序实现
- 【数据结构】之队列的java实现(二)
- 数据结构 第三章-- 循环队列(队列的顺序表示和实现)
- 请实现一个队列,既可以存放整数,又可以存放字符串。简单的说,队列是一种数据结构,按照先进先出的顺序管理进、出队列的元素
- java数据结构之LinkedQueue(用链表实现的双端单向队列)