Java 数据结构之队列

一、队列的介绍 

     队列(Queue)是一种特殊的线性表,限定只能在表的一端进行插入(队尾),而在另一端进行删除操作(队头),特点是“先进先出”(FIFO)。队列的使用方式为通过Queue接口的实现类来创建对象,比较常见的实现类有LinkedList、ArrayDeque、PriorityQueue,通常使用LinkedList来创建队列新对象即可,样例代码为Queue<String> queue = new LinkedList<> () ;这里穿插一些个人理解,通过LinkedList我们可以创建Queue对象,也可以创建LinkedList对象,即LinkedList<String> queue = new LinkedList<> ();但是具体在调用方法时使用的是各自(队列和链表)的方法,这说明还是要看创建的是什么类型的对象,即使这里二者都是通过相同的类来创建得到的对象。 

       队列的基本操作包括压入元素(添加):offer()、弹出元素(删除):poll()、获取队头元素(不删除):peek()。使用以上三种方法即可。样例代码分别为:queue.offer("12");queue.poll();String str  = queue.peek();。

二、Java实现自定义队列

       自定义一个队列,队列的底层采用数组。然后使用front和end来代表队尾插入位置的指针和队头弹出元素的指针,然后使用nItems来代表当前队列中元素的个数。 然后创建insert、remove方法来压入数据和弹出数据,peekFront方法来得到队列队头的数据,isEmpty来判定队列是否为空,isFull方法来判断队列是否已满。如下代码表示的是循环队列的实现,可以得到正确的测试结果。

1 循环队列

       为了避免队列不满,却不能插入新数据项的问题,可以让队头队尾的指针绕回到数组开始的位置,这就是循环队列,也称为缓冲环。

package com.ms.MyQueue;

public class MyQueue {
    //存入队列数据的数组,自定义队列的底层是数组,这里先用int数组
    private int[] queue;
    //使用front来表示弹出数据的指针,默认为0;
    private int front;
    //使用end来表示压入数据的指针,默认为-1,每次使用时先加1;
    private int end;
    //使用nItems来表示当前队列中元素的个数
    private int nItems;

    //构造函数
    public MyQueue(int length){
        queue = new int[length];
        front = 0;
        end   = -1;
        nItems = 0;
    }



    //压入数据的方法
    public void insert(int data){
        //先对end进行一个判定,如果到了底层数组的最后一位,那么就让它让返回至首位
        if(end==queue.length-1){
            end=-1;
        }
        end++;
        queue[end] = data;
        nItems++;
        if (nItems>queue.length){
            nItems= queue.length;
        }
    }

    //弹出数据的方法
    public int remove(){
        //根据已存放数据的个数来首先判断
        if(nItems==0){
            return 0 ;
        }
        //找媒介暂时存放数组数据
        int temp = queue[front];
        queue[front]=0;

        //front+1之前维护一下,说的是当front是底层数组最后一位时的情况
        if (front== queue.length-1){
            front=-1;
        }
        //取完了数据之后,将front加1
        front++;
        return temp;
    }

    //获取队头处的数据
    public int peekFront(){
        return queue[front];
    }
    //判断队列是否为空
    public boolean isEmpty(){
        return nItems==0;
    }

    //判断队列是否已满
    public boolean isFull(){
        return  nItems== queue.length;
    }
    //清空队列
    public void clear(){
        queue = new int[queue.length];
    }

    public static void main(String[] args) {
        MyQueue que = new MyQueue(6);
        que.insert(1);
        que.insert(9);
        que.insert(9);
        que.insert(7);
        que.insert(0);
        que.insert(8);

        System.out.println(que.remove());
        System.out.println(que.isFull());
        //System.out.println(que.remove());
        que.remove();
        que.remove();
        que.remove();
        que.remove();
        que.remove();
        System.out.println(que.front);

    }
    
}

2 双端队列

       所谓双端队列,就是一个两端都可以进行数据插入和移出操作的队列。它综合提供了栈和队列的功能,但并不常见。

3 优先级队列

       优先级队列就是数据项按照关键字排好顺序的队列,即队列中的数据按顺序排列。

       思考一下可以想到,优先级队列相比于普通(循环)队列不同之处应该是在插入时要进行排列。因为涉及排序,就尽量不循环,所以插入队尾指针end和弹出队头指针front就先不要了(nItems记录了当前队列里存放的元素个数,也相当于是索引),并且在创建对象的时候要把length设置的大一些就可以了。然后在插入数据的过程中我们使用到了 插入法排序,从而使得队列中的数据升序或者降序。以下是优先级队列的代码,运行后可以得到正确结果

package com.ms.MyQueue;

import javafx.scene.layout.Priority;

public class PriorityQueue {
    //优先级队列的底层是数组,这里先默认类型是整数
    private int[] queue;
    //使用nItems来表示当前队列中元素的个数
    private int nItems;

    //无参构造函数
    public PriorityQueue(){}
    //有参构造函数
    public PriorityQueue(int length){
        queue = new int[length];
        nItems = 0;
    }

    //插入方法
    public void insert(int data){
        //队列中没有数据的话就直接加入
        if(nItems==0){
            queue[nItems]=data;
        }else{
            //使用插入法进行排序,把数据放入合适的位置(由大到小的顺序,这样的话按照nItems取数据时就按照由小到大的顺序取)
            int i = 0;
            for ( i=nItems-1;i>=0;i--){
                if (data>queue[i]){
                    queue[i+1]=queue[i];
                }else{
                    break;
                }
            }
            queue[i+1]=data;
        }
        nItems++;
    }

    //弹出方法
    public int remove(){
        //取得时候先取最小的
        //先减小
        nItems--;
        int tep = queue[nItems];
        return tep;
    }
    //取队头值
    public int peekfront(){
        return queue[nItems-1];
    }
    public boolean isEmpty(){
        return nItems==0;
    }
    public boolean isFull(){
        return nItems== queue.length;
    }

    public static void main(String[] args) {
        PriorityQueue que = new PriorityQueue(10);
        que.insert(2);
        que.insert(5);
        que.insert(4);
        que.insert(6);
        que.insert(1);
        que.insert(3);
        System.out.println(que.remove());
        System.out.println(que.remove());
        System.out.println(que.remove());
        System.out.println(que.remove());
        System.out.println(que.remove());
        System.out.println(que.remove());

    }











}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值