保安日记之队列(自己实现)

一、前言

1.1 队列的概念

通过之前的集合框架图示可以看到队列(Queue)是一个接口,只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,进行插入操作的一端称为队尾,进行删除操作的一端称为队头

1.2 队列的特点

队列具有先进先出的特点。

1.3 队列的操作

与上篇博客介绍的栈一样,队列相当于对线性表的功能进行了限制.基本操作就是以下三种:
1.入队列(从队尾插入元素)
2.出队列(删除队首的元素)
3.取队首元素(获取到队首位置的元素的值)

1.4 队列的变种

1.普通的队列:先出先进的规则
2.优先出队列:出队列的顺序和入队列的顺序不一样,每次出队列的元素都是优先级最高的元素(本质上是一个堆)
3.消息队列:也不是严格的先进先出,而是按照"类型"来获取元素(业务类型)(实际工作中会用到很多的"消息队列服务器")
4.阻塞队列:当队列为空的时候,出队列操作就会阻塞;当队列为满的时候,入队列操作就会阻塞(代码执行到某个地方就不往下走了,一直等待)
5.无锁队列:线程安全的队列,不是通过锁来实现线程安全 比较高效 CAS操作来实现的

二、队列的实现

2.1 基于数组实现队列

public class MyQueueByArrayList {
    private int[] array=new int[100];
    //[head,tail)初始情况下队列中应该是没有元素的
    private int head=0;
    private int tail=0;
    private int size=0;

    //如果插入成功返回true
    //如果插入失败返回false
    public boolean offer(int value){
        if(size==array.length){
            return false;
        }
        array[tail]=value;
        tail++;
        if(tail>=array.length){
            tail=0;
        }
        //tail=tail%array.length
        size++;
        return true;
    }
    public Integer poll(){
        if(size==0){
            //队列为空,出队列失败
            return null;
        }
        //队列非空,返回head位置的元素,同时head++ 删除该元素
        int ret=array[head];
        head++;
        if(head>=array.length){
            head=0;
        }
        size--;
        return ret;
    }
    public Integer peek(){
        if(size==0){
            return null;
        }
        return array[head];
    }

    public static void main(String[] args) {
        MyQueueByArrayList queue=new MyQueueByArrayList();
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        queue.offer(4);
        while(true){
            Integer cur=queue.poll();
            if(cur==null){
                break;
            }
            System.out.println(cur);
        }
    }
}

2.2 基于链表实现队列
链表的方式来实现更简单一些,链表的尾部作为队尾(方便插入元素) 链表头部作为队首(方便删除元素),为了方便的实现尾插,多搞一个引用指向链表的尾部,这里为了方便实现也用到了傀儡结点

public class MyQueueByLinkedList {
    static class Node{
        public int val;
        public Node next;

        public Node(int val) {
            this.val = val;
        }
    }
    private Node head=new Node(-1);
    private Node tail=head;

    private int size;//队列中的元素个数
    //入队列(链表尾插)
    public void offer(int value){
        Node newNode=new Node(value);
        //核心操作就是这一行代码
        tail.next=newNode;
        tail=tail.next;
    }
    //出队列(链表头删)
    public Integer poll(){
        if(head.next==null){
            //队列为空,出队列失败
            return null;
        }
        Node toDelete=head.next;
        head.next=toDelete.next;
        if(head.next==null){
            //此时队列已经为空了.
            //让tail指回傀儡结点
            tail=head;
        }
        return toDelete.val;
        //不要忘了更新尾部
    }
    //取队首元素
    public Integer peek(){
        if(head.next==null){
            //空队列
            return null;
        }
        return head.next.val;
    }

    public static void main(String[] args) {
        MyQueueByLinkedList queue=new MyQueueByLinkedList();
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        queue.offer(4);
        while(true){
            Integer cur=queue.poll();
            if(cur==null){
                break;
            }
            System.out.println(cur);
        }
    }
}

这里就是用两种方式来自己实现队列的全部代码,核心思想就是先进先出
外加一个小tips:
1.链表版本的队列:插入元素无上限,效率更低,需要额外的内存空间保存引用地址
2.数组版本的队列:插入元素有上限,效率更高,不需要额外空间保存引用地址
3.标准库中的队列Queue基于链表实现的,后面在工作中接触到的很有可能是用数组版本实现的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值