Java数据结构之队列

一.概述

1.队列(queue)是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
2.队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。

二.队列的分类

1.单向队列:只能在一端插入数据,另一端删除数据。可以使用数组和链表两种方式来实现,遵循先入先出(FIFO)的规则,即先进入的数据先出。单向队列属于有序列表。
2.双向队列:每一端都可以进行插入数据和删除数据操作。
3.优先级队列:优先级队列是比栈和队列更专用的数据结构,在优先级队列中,数据项按照关键字进行排序,关键字最小(或者最大)的数据项往往在队列的最前面,而数据项在插入的时候都会插入到合适的位置以确保队列的有序。一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。

三.三种队列的Java实现

1.单向队列
(1)示意图

(2)代码实现

public class Queue {
    private Object[] queArray;
    //队列总大小
    private int maxSize;
    //队头指针
    private int front;
    //队尾指针
    private int rear;
    //队列中元素的实际数目
    private int count;

    public Queue(int s){
        maxSize = s;
        queArray = new Object[maxSize];
        front = 0;
        rear = -1;
        count = 0;
    }

    //入队
    public void insert(int value){
        if(isFull()){
            System.out.println("该队列已满,无法入队");
        }else{
            //队尾指针指向队头
            if(rear == maxSize -1){
                rear = -1;
            }
            //队尾指针加1,然后在队尾指针处插入新的数据
            queArray[++rear] = value;
            count++;
        }
    }

    //移除数据
    public Object remove(){
        Object removeValue = null ;
        if(!isEmpty()){
            removeValue = queArray[front];
            queArray[front] = null;
            front++;
            if(front == maxSize){
                front = 0;
            }
            count--;
            return removeValue;
        }
        return removeValue;
    }

    //查看队头
    public Object peekFront(){
        return queArray[front];
    }


    //判断队列是否满了
    public boolean isFull(){
        return (count == maxSize);
    }

    //判断队列是否为空
    public boolean isEmpty(){
        return (count ==0);
    }

    //返回队列的大小
    public int getSize(){
        return count;
    }
}

2.双向队列
(1)代码实现

3.优先级队列
(1)代码实现

使用数组来实现优先级队列
public class PriorityQueue{
        private int maxSize;
        private int[] priQueArray;
        private int count;

        public PriorityQueue(int s){
            maxSize = s;
            priQueArray = new int[maxSize];
            count = 0;
        }

        //插入数据
        public void insert(int value){
            int i;
            if(count == 0){
                priQueArray[count++] = value;
            }else{
                i = count -1;
                //插入排序,按照从大到小的顺序排列,越小的越在队列的顶端
                while(i >=0 && value > priQueArray[i]){
                    priQueArray[i+1] = priQueArray[i];
                    i--;
                }
                priQueArray[i+1] = value;
                count++;
            }
        }
        
        public int remove(){
            int k = count -1;
            int value = priQueArray[k];
            priQueArray[k] = -1;//-1表示这个位置的数据被移除了
            count--;
            return value;
        }

        //查看优先级最高的元素
        public int peekMin(){
            return priQueArray[count -1];
        }

        //判断队列是否为空
        public boolean isEmpty(){
            return (count == 0);
        }

        //判断队列是否满了
        public boolean isFull(){
            return (count == maxSize);
        }
}

四.Java队列一些常用方法的区别

1.offer(),add() 区别:
一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。
这时新的 offer()方法就可以起作用了。它不是对调用 add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false。
2.poll(),remove() 区别:
remove() 和 poll() 方法都是从队列中删除第一个元素。remove() 的行为与 Collection 接口的版本相似, 但是新的 poll() 方法在用空集合调用时不是抛出异常,只是返回 null。因此新的方法更适合容易出现异常条件的情况。
3.peek(),element()区别:
element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null。

五.队列的应用场景

一般情况下,如果是对一些及时消息的处理,并且处理时间很短的情况下是不需要队列的,直接阻塞式的方法调用就可以了。但是如果在消息处理的时候特别费时间,这个时候如果有新消息来了,就只能处于阻塞状态,造成用户等待。这个时候便需要引入队列了。当接收到消息后,先把消息房贷队列中,然后再用行的线程进行处理,这个时候就不会有消息阻塞了。队列先入先出的特点,使得其应用非常广泛,比如队列作为“缓冲区”,可以解决计算机和外设速度不匹配的问题,FIFO的特点保证了数据传输的顺序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值