Java数据结构之队列

队列的基本介绍

队列,是一个线性表,分为顺序队列和链式队列,本节我们说的是顺序队列。

队列存储在一段连续的存储空间之内(数组),它自身的特点是:先进先出,即从队尾添加元素,对头删除元素。

在平时的生活中,打印机等等用到的原理都是队列。

接下来我所讲的跟队列有关的内容分为两种:普通队列,循环队列。下面所有的代码都是可执行的(本人编写,亲测可用),写了一个小程序,用来实现队列的各种方法。

普通队列

示意图如下:

 

 

 在这个队列中,我们暂定指向对头的指针为front,指向队尾的指针为rear,我们将front和rear的初始值都设置为-1,front会随着数据的输出而改变,rear也会随着数据的输入而改变。其次,在这个图中我们可以发现,我们需要给定一个数组的最大长度maxSize,并且显示一个数组。因此,我们可以得出的结论就是,在我们Java的构造函数中应该有4个元素:front,rear,maxSize,int[] arr;

关于普通队列的操作,由上图所示:

(1).当队列为空时:

front == rear;

 

(2).当队列为满时:

rear = maxSize-1;

 

(3).当添加队列元素时(假设添加的元素是n):

rear++;

arr[rear] = n;

 

(4).当删除队列元素时(这时,我们的程序需要返回删除的元素的值):

int value = 0;

front++;

value = arr[front];

 

(5).当遍历这个队列中的元素的时候,相应的,我们只需要遍历这个数组即可。

 

代码展示

在下面的代码中我会用注释说明,添加元素,删除元素等等的队列操作。(使用的编译器是Eclipse)

package queue;

import java.util.Scanner;

public class ArrayQueueDemo_1 {

    public static void main(String[] args) {
        
        ArrayQueued que = new ArrayQueued(4);
        
        Scanner sc = new Scanner(System.in);
        //用于用户的输入
        char key = ' ';
        //标志变量
        boolean flag = true;
        while(flag){
        
            System.out.println("显示队列元素:s");
            System.out.println("添加队列元素:a");
            System.out.println("删除队列元素:d");
            System.out.println("显示队头元素:h");
            System.out.println("退出程序:e");
            //charAt(0)相当于将字符串用字符返回
            key = sc.next().charAt(0);
            switch(key){
            case 'a':
                System.out.println("输入一个数字");
                int value = sc.nextInt();
                que.add(value);
                break;
            case 'd':
                int d = que.delete();
                System.out.println(d);
                break;
            case 'h':
                que.head();
                break;
            case 's':
                que.show();
                break;
            case 'e':
                sc.close();
                flag = false;
                break;
            default:
                break;
            }
        }
        System.out.println("程序结束");
    }
}    

//创建了一个队列的类,用来执行队列的各种操作
class ArrayQueued{
    private int front;  
    private int rear;
    private int[] arr;
    private int maxSize;
    
    //构造器,给指定的元素赋值
    public ArrayQueued(int maxSize){
        front = -1;                  //front的初始值是-1
        rear = -1;                   //rear的初始值是-1
        this.maxSize = maxSize;      //maxSize的初始值由用户输入
        arr = new int[maxSize];      //开辟maxSize大小的数组
    }
    
    //判断队列是否为空
    public boolean isEmpty(){
        return front == rear;           
    }
    
    //判断队列是否为满
    public boolean isFull(){
        return rear == maxSize - 1;
    }
    //向队列添加元素
    public void add(int n){
        try{
            if(isFull()){
                System.out.println("队列已经满,不能添加~");
                return;
            }
            rear++;
            arr[rear] = n;
            
        }catch(Exception ex){
            System.out.println(ex.getMessage());
        }
    }
    //删除队列的元素
    public int delete(){
        if(isEmpty()){
            System.out.println("队列为空,不能删除~");
        }
        front++;
        int value = arr[front];
        arr[front] = 0;   //这个赋值是将删除元素的值全变成0
        return value;
    }
    
    //显示队列中的元素
    public void show(){
        if(isEmpty())
            System.out.println("队列为空,没有数据!");
        for(int i=0;i<arr.length;i++){
            System.out.printf("arr[%d] = %d\t",i,arr[i]);
        }
        System.out.println();
    }
    //显示队列中的第一个元素
    public void head(){
        if(isEmpty()){
            System.out.println("队列为空!");
        }
        System.out.printf("对头元素:%d",arr[front+1]);
        System.out.println();
    }
    
}
    

 

循环队列

刚刚看完了普通队列,它虽然方便,但是有着很大的缺点,就是浪费内存空间(随着front,rear的增加,front下面的元素没法利用了),循环队列就是在普通队列的基础上进行了优化,让整个队列变成一个环,这样所有的空间都可以利用。

关于循环队列的表述:

(1).当队列为空时:

front == rear;

 

(2).当队列为满时:我们约定,尾索引的下一个元素为头索引时表示队列满,即:将队列容量空出一个作为约定

(rear+1)%maxSize == front;

 

(3).整个队列中元素的个数

(rear+maxSize-front)%maxSize

 

循环队列的表示跟普通队列有点不同,具体代码如下图所示

package queue;

import java.util.Scanner;

public class ArrayQueueCircle {

    public static void main(String[] args) {
        
        ArrayQueuec que = new ArrayQueuec(4);
        
        Scanner sc = new Scanner(System.in);
        //用于用户的输入
        char key = ' ';
        //标志变量
        boolean flag = true;
        while(flag){
        
            System.out.println("显示队列元素:s");
            System.out.println("添加队列元素:a");
            System.out.println("删除队列元素:d");
            System.out.println("显示队头元素:h");
            System.out.println("退出程序:e");
            //charAt(0)相当于将字符串用字符返回
            key = sc.next().charAt(0);
            switch(key){
            case 'a':
                System.out.println("输入一个数字");
                int value = sc.nextInt();
                que.add(value);
                break;
            case 'd':
                int d = que.delete();
                System.out.println(d);
                break;
            case 'h':
                que.head();
                break;
            case 's':
                que.show();
                break;
            case 'e':
                sc.close();
                flag = false;
                break;
            default:
                break;
            }
        }
        System.out.println("程序结束");
    }
}    


class ArrayQueuec{
    private int front;
    private int rear;
    private int[] arr;
    private int maxSize;
    
    //构造器
    public ArrayQueuec(int maxSize){
        this.maxSize = maxSize;
        arr = new int[maxSize];
    }
    
    //判断队列是否为空
    public boolean isEmpty(){
        return front == rear;
    }
    
    //判断队列是否为满
    public boolean isFull(){
        return (rear+1)%maxSize == front;
    }
    
    //队列长度
    public int size(){
        return (rear+maxSize-front)%maxSize;
    }
    
    //向队列添加元素
    public void add(int n){
        try{
            if(isFull()){
                System.out.println("队列已经满,不能添加~");
                return;
            }
            
            arr[rear] = n;
            rear = (rear+1)%maxSize;
            
        }catch(Exception ex){
            System.out.println(ex.getMessage());
        }
    }
    //删除队列的元素
    public int delete(){
        if(isEmpty()){
            System.out.println("队列为空,不能删除~");
        }
        int value = arr[front];
        front = (front+1)%maxSize;
        return value;
    }
    
    //显示队列中的元素
    public void show(){
        if(isEmpty())
            System.out.println("队列为空,没有数据!");
        for(int i=front;i<front+size();i++){
            System.out.printf("arr[%d] = %d\t",i%maxSize,arr[i%maxSize]);
        }
        System.out.println();
    }
    //显示队列中的第一个元素
    public void head(){
        if(isEmpty()){
            System.out.println("队列为空!");
        }
        System.out.printf("对头元素:%d",arr[front]);
        System.out.println();
    }
    
}
    

 

主要关注一下添加,删除还有遍历的不同~~~

 

posted @ 2019-09-27 10:28  小白菜也有明天  阅读(354)  评论(0编辑  收藏  举报