您现在的位置是:首页 >技术杂谈 >数据结构与算法练习(二)数组模拟队列网站首页技术杂谈

数据结构与算法练习(二)数组模拟队列

贫僧洗发爱飘柔 2024-08-12 12:01:04
简介数据结构与算法练习(二)数组模拟队列


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];
    }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。