赞
踩
银行排队、餐厅网上叫号系统使用的都是队列这种数据结构。
使用数组模拟队列示意图:
队列本身是有序列表, 其中 maxSize 是该队列的最大容量。例如当队列最大长度MaxSize=5时:
约定rear总是指向队尾元素,front指向当前队中队头元素的前一位置 。
元素进队,rear增1,元素出队,front增1。
当rear=MaxSize-1时不能再进队。
存入队列时称为”enQueue”,enQueue 的处理需要有两个步骤:
// 执行队列的初始化操作
public ArrayQuene(int maxSize) {
this.maxSize = maxSize;
rear = -1; // 队尾元素
front = -1; // 队头元素
arr = new int[maxSize];
}
// 判断队列是否已满
public boolean isFull(){
return rear == maxSize - 1;
}
// 判断队列是否为空
public boolean isEmpty(){
return rear == front;
}
// 将数据添加到队列
public void enQuene(int data){
// 判断队列是否已满
if(!isFull()){
arr[++rear] = data;
System.out.println("进队成功!");
} else {
System.out.println("队列已满,不能添加数据!");
}
}
// 获取队列元素,出队
public void deQuene(){
if(!isEmpty()){
System.out.println(arr[++front]);
System.out.println("元素:" + arr[front] + "出队成功!");
}else{
System.out.println("队列为空,出队失败!");
}
}
// 输出队列中的所有值
public void showQuene(){
if(!isEmpty()){
for(int i = 0; i < arr.length;i++){
if(i > front && i <= rear){
System.out.print(arr[i] + " ");
}
}
}else{
System.out.println("队列为空!");
}
}
// 获取队头元素
public void getHead(){
if(!isEmpty()){
System.out.println("队头元素为:" + arr[front + 1 ] );
}else{
System.out.println("队列为空,无队头元素!");
}
}
public static void main(String[] args) { ArrayQuene arrayQuene = new ArrayQuene(5); String key = null; Scanner sc = new Scanner(System.in); boolean index = true; while(index){ System.out.println("============================"); System.out.println("show:显示队列"); System.out.println("en :进队"); System.out.println("de :出队"); System.out.println("head:显示队头"); System.out.println("exit:退出程序"); System.out.println("============================"); key = sc.nextLine(); switch (key){ case "show": arrayQuene.showQuene(); break; case "en": System.out.println("请输入进队元素"); int data = sc.nextInt(); arrayQuene.enQuene(data); break; case "de": arrayQuene.deQuene(); break; case "head": arrayQuene.getHead(); break; case "exit": sc.close(); index = false; break; default: break; } } System.out.println("程序已退出!"); } public static class ArrayQuene{ private int maxSize; private int front; private int rear; private int[] arr; // 存储数据的值 // 执行队列的初始化操作 public ArrayQuene(int maxSize) { this.maxSize = maxSize; rear = -1; // 队尾元素 front = -1; // 队头元素 arr = new int[maxSize]; } // 判断队列是否已满 public boolean isFull(){ return rear == maxSize - 1; } // 判断队列是否为空 public boolean isEmpty(){ return rear == front; } // 将数据添加到队列 public void enQuene(int data){ // 判断队列是否已满 if(!isFull()){ arr[++rear] = data; System.out.println("进队成功!"); } else { System.out.println("队列已满,不能添加数据!"); } } // 获取队列元素,出队 public void deQuene(){ if(!isEmpty()){ System.out.println(arr[++front]); System.out.println("元素:" + arr[front] + "出队成功!"); }else{ System.out.println("队列为空,出队失败!"); } } // 输出队列中的所有值 public void showQuene(){ if(!isEmpty()){ for (int i : arr) { System.out.println(i + " "); } }else{ System.out.println("队列为空!"); } } // 获取队头元素 public void getHead(){ if(!isEmpty()){ System.out.println("队头元素为:" + arr[front + 1 ] ); }else{ System.out.println("队列为空,无队头元素!"); } } }
使用顺序队列有一个问题:当队满之后,经过几次出队操作后,队列中虽然存在空位置,但是不能执行进队操作,具体情形如下图:
这是因为采用rear==MaxSize-1作为队满条件的缺陷。当队满条件为真时,队中可能还有若干空位置。
这种溢出并不是真正的溢出,称为假溢出。
解决方案就是把数组的前端和后端连接起来,形成一个环形的顺序表,即把存储队列元素的表从逻辑上看成一个环,称为环形队列或循环队列。
实际上内存地址一定是连续的,不可能是环形的,这里是通过逻辑方式实现环形队列,也就是将rear++和front++改为:
现在约定rear=front为队空,以下两种情况都满足该条件:
并约定(rear+1)%MaxSize=front为队满条件
当进队一个元素就到达队头时,就认为队满了。这样做会少放一个元素,牺牲一个元素没关系的
队空条件:front = rear
队满条件:(rear+1)%MaxSize = front
进队e操作:rear=(rear+1)%MaxSize; 将e放在rear处
出队操作:front=(front+1)%MaxSize; 取出front处元素e;
在环形队列中,实现队列的基本运算算法与非环形队列类似,只是改为上述4要素即可。
// 初始化环形队列
public CircleArray(int maxSize){
this.maxSize = maxSize;
// 定义front执行环形队列的第一个元素,而非顺序队列中执行队头的前一个元素,rear同理
front = 0;
rear = 0;
arr = new int[maxSize];
}
// 判断是否满
public boolean isFull(){
return (rear + 1 ) % maxSize == front;
}
// 判断是否为空
public boolean isEmpty(){
return rear == front;
}
// 进队
public void enQuene(int data){
if(!isFull()){
// 注意与顺序队列的区别
arr[rear++] = data;
rear = rear % maxSize;
System.out.println("元素:" + data + "进队成功!");
}else {
System.out.println("队列已满,进队失败!");
}
}
// 出队
public void deQuene(){
if(!isEmpty()){
System.out.println("元素:" + arr[front++] + "出队成功!");
front = front % maxSize;
}else{
System.out.println("队列为空,出队失败!");
}
}
// 输出队列中的元素
public void showQuene(){
if(!isEmpty()){
// front从零开始
for(int i = front; i < front + size(); i++) {
// 当i大于rear时,说明队列已满且经过出队操作
// 针对这种情况,输出rear后所有元素
if ( (i >= front && i < rear) || (i > rear) ) {
System.out.print(arr[i % maxSize] + " ");
}
}
}else{
System.out.println("队列为空!");
}
}
// 求出数据中的元素个数,从1开始
public int size(){
return (rear + maxSize - front) % maxSize;
}
// 获取头元素
public void getHead(){
System.out.println("队头元素为:" + arr[front % maxSize]);
}
package com.hzy.datastructs; import java.util.Scanner; public class CircleArrayDemo { public static void main(String[] args) { CircleArray circleArray = new CircleArray(5); String key = null; Scanner sc = new Scanner(System.in); boolean index = true; while(index){ System.out.println("============================"); System.out.println("show:显示队列"); System.out.println("en :进队"); System.out.println("de :出队"); System.out.println("head:显示队头"); System.out.println("exit:退出程序"); System.out.println("============================"); key = sc.nextLine(); switch (key){ case "show": circleArray.showQuene(); break; case "en": System.out.println("请输入进队元素"); int data = sc.nextInt(); circleArray.enQuene(data); break; case "de": circleArray.deQuene(); break; case "head": circleArray.getHead(); break; case "size": circleArray.size(); break; case "exit": sc.close(); index = false; break; default: break; } } System.out.println("程序已退出!"); } public static class CircleArray{ private int[] arr; private int front; private int rear; private int maxSize; // 初始化环形队列 public CircleArray(int maxSize){ this.maxSize = maxSize; // 定义front执行环形队列的第一个元素,而非顺序队列中执行队头的前一个元素,rear同理 front = 0; rear = 0; arr = new int[maxSize]; } // 判断是否满 public boolean isFull(){ return (rear + 1 ) % maxSize == front; } // 判断是否为空 public boolean isEmpty(){ return rear == front; } // 进队 public void enQuene(int data){ if(!isFull()){ // 注意与顺序队列的区别 arr[rear++] = data; rear = rear % maxSize; System.out.println("元素:" + data + "进队成功!"); }else { System.out.println("队列已满,进队失败!"); } } // 出队 public void deQuene(){ if(!isEmpty()){ System.out.println("元素:" + arr[front++] + "出队成功!"); front = front % maxSize; }else{ System.out.println("队列为空,出队失败!"); } } // 输出队列中的元素 public void showQuene(){ if(!isEmpty()){ // front从零开始 for(int i = front; i < front + size(); i++) { // 当i大于rear时,说明队列已满且经过出队操作 // 针对这种情况,输出rear后所有元素 if ( (i >= front && i < rear) || (i > rear) ) { System.out.print(arr[i % maxSize] + " "); } } }else{ System.out.println("队列为空!"); } } // 求出数据中的元素个数,从1开始 public int size(){ return (rear + maxSize - front) % maxSize; } // 获取头元素 public void getHead(){ System.out.println("队头元素为:" + arr[front % maxSize]); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。