您现在的位置是:首页 >技术杂谈 >数据结构与算法练习(二)数组模拟队列网站首页技术杂谈
数据结构与算法练习(二)数组模拟队列
简介数据结构与算法练习(二)数组模拟队列
1、队列
队列是一个有序列表,可以用数组或链表来实现
遵循先入先出的原则
在队尾插入元素叫做入队,对头删除元素叫做出队。
2、数组实现队列
思路:
- 用front和rear记录队列前后的下标,初始化front=-1表示指向队列的头部(队列头的前一个位置),rear=-1指向队列尾(队列的最后一个数据)
- 若尾指针rear小于队列的最大下标MaxSize-1,则rear+1尾指针往后移,若rear=MaxSize-1,则队列满。
- 若出队,头指针front+1后移,若rear=front。队列为空。
代码实现:
package Que;
/*
* 数组模拟队列
* */
import java.util.Scanner;
public class ArrToQue {
public static void main(String[] args) {
//创建一个尺寸为5的队列
Queue queue = new Queue(5);
Scanner scanner = new Scanner(System.in);
char key=' ';
boolean loop=true;
while (loop){
System.out.println("d:显示队列");
System.out.println("e:退出程序");
System.out.println("a:添加数据到队列");
System.out.println("b:从队列取出数据");
System.out.println("c:查看队列头部数据");
key=scanner.next().charAt(0); //获取用户输入的第一个字符
switch (key){
case 'a':
System.out.println("请输入一个数");
int value= scanner.nextInt();
queue.addQueue(value);
break;
case 'b':
try{
int res = queue.delQue();
System.out.println("去除的数据为:"+res);
}catch (Exception e){
System.out.println(e.getMessage());//低下抛出异常,这里捕捉异常信息
}
break;
case 'c':
try{
int res = queue.headQue();
System.out.println("头数据为:"+res);
}catch (Exception e){
System.out.println(e.getMessage());//低下抛出异常,这里捕捉异常信息
}
break;
case 'd':
queue.showQue();
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
}
}
/*定义一个队列
* */
class Queue{
int maxSize ;
int front;
int rear;
int[] arr;
//通过构造方法初始化
public Queue(int maxSize) {
this.maxSize = maxSize;
this.front = -1;
this.rear = -1;
this.arr = new int[maxSize];
}
//判断队列是否为空
public boolean isNull(){
//初始化都为-1为true,队列数据都取完front=rear=maxSize-1
return front==rear;
}
//判断队列是否是满的
public boolean isFull(){
return rear==maxSize-1;
}
//队列中添加数据
public void addQueue(int data){
//先判断队列是不是满的
if(isFull()){
//抛出运行时异常
System.out.println("队列已经满了");
}else {
rear++;
arr[rear]=data;
}
}
//从队列中删除数据
public int delQue(){
//首先判断队列是否为空
if (isNull()){
throw new RuntimeException("队列为空");
//System.out.println("队列为空");
}else {
front++;
return arr[front];//返回删除的数据
}
}
//遍历队列
public void showQue(){
if (isNull()){
System.out.println("队列为空");
}else {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
//显示队列的头数据
public int headQue(){
if (isNull()){
throw new RuntimeException("队列为空");
}
return arr[++front];//比如删除第一个数据front从-1变为0,此时头数据的指针应该指向第二个元素也就是下标为1数据
}
}
这样实现队列有缺点:
队列只能使用一次(数组尺寸是固定的,添加满了就不能添加了
,只是指针发生改变),
不能达到复用的效果
3、数组实现循环队列
实现思路:
-
front指向指向队列的第一个元素,初始化front=0, rear指向队列的最后一个元素的后一个位置,初始化rear=0,空出一个空间作为约定。
-
当队列满时(rear+1)%maxSize=front
-
当队列空时 front=rear
-
入队rear=(rear+1)%maxSize
-
出队front = (front+1)%maxSize
-
队列中的有效数据:(rear + maxSize - front) %maxSize
假设maxSize=3,实际上只能存储2个元素,初始化front=0,rear=0; 入队一个元素 添加: front=0 arr[rear=0] rear后移: rear=(rear+1)%maxSize=(0+1)%3=1 继续添加:front=0 arr[rear=1] rear后移: (1+1)%3=2 此时rear=(rear+1)%maxSize=(2+1)%3=0=front所以队列已经 满了 出队一个元素 出队: front=0 front后移: front = (front+1)%maxSize=(0+1)%3=1; 继续出队: front=1 front后移: front = (front+1)%maxSize=(1+1)%3=2; 此时front=(front+1)%maxSize=(2+1)%3=0=rear所以队列已经 空了 队列中的有效数据:(rear + maxSize - front) %maxSize 添加两个元素rear=2,删除一个front=1.有效数据为(2+3-1)%3=1 0 2 (0+3-2)%3=1 0 1 (0+3-1)%3=2 2 1 (2+3-1)%3=1 0 0 (0+3-0)%3=0
package Que;
import java.util.Scanner;
/*数组模拟循环队列
* */
public class ArrToCirQue {
public static void main(String[] args) {
//创建一个尺寸为5的队列
CirQueue queue = new CirQueue(3);
Scanner scanner = new Scanner(System.in);
char key=' ';
boolean loop=true;
while (loop){
System.out.println("d:显示队列");
System.out.println("e:退出程序");
System.out.println("a:添加数据到队列");
System.out.println("b:从队列取出数据");
System.out.println("c:查看队列头部数据");
key=scanner.next().charAt(0); //获取用户输入的第一个字符
switch (key){
case 'a':
System.out.println("请输入一个数");
int value= scanner.nextInt();
queue.addQueue(value);
break;
case 'b':
try{
int res = queue.delQue();
System.out.println("去除的数据为:"+res);
}catch (Exception e){
System.out.println(e.getMessage());//低下抛出异常,这里捕捉异常信息
}
break;
case 'c':
try{
int res = queue.headQue();
System.out.println("头数据为:"+res);
}catch (Exception e){
System.out.println(e.getMessage());//低下抛出异常,这里捕捉异常信息
}
break;
case 'd':
queue.showQue();
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
}
}
class CirQueue{
int maxSize ;
int front;
int rear;
int[] arr;
//通过构造方法初始化
public CirQueue(int maxSize) {
this.maxSize = maxSize;
this.arr = new int[maxSize];
}
//判断队列是否为空
public boolean isNull(){
//初始化都为0为true
return front==rear;
}
//判断队列是否是满的
public boolean isFull(){
return front==(rear+1)%maxSize;
}
//队列中添加数据
public void addQueue(int data){
//先判断队列是不是满的
if(isFull()){
//抛出运行时异常
System.out.println("队列已经满了");
}else {
arr[rear]=data;//先放元素再后移
rear=(rear+1)%maxSize;
}
}
//从队列中删除数据
public int delQue(){
//首先判断队列是否为空
if (isNull()){
throw new RuntimeException("队列为空");
//System.out.println("队列为空");
}else {
int value = arr[front];
front = (front+1)%maxSize;
return value;
}
}
//遍历队列
public void showQue(){
if (isNull()){
System.out.println("队列为空");
}else {
for (int i = front; i < front + (rear + maxSize - front) %maxSize; i++) {
System.out.println(arr[i% maxSize]+"下标为"+i% maxSize);
}
}
}
//显示队列的头数据
public int headQue(){
if (isNull()){
throw new RuntimeException("队列为空");
}
return arr[front];
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。