数据结构与算法——13.队列的拓展

这篇文章主要讲一下双端队列,优先队列,阻塞队列等队列的拓展内容。

目录

1.队列拓展概述

2.双端队列的链表实现

3.双端队列的数组实现

4.优先队列无序数组实现

5.阻塞队列

6.总结


1.队列拓展概述

首先来看一张图,来大致了解一下他们的区别。

双端队列:即两端都可以删除和添加的队列,并且满足队列FIFO的特点。

2.双端队列的链表实现

下面来看一下双端队列的链表实现:

代码如下:

/**
 * 基于双向环形链表实现双端队列
 * */
public class L15_LinkedListDeque<E> implements L15_TwoQueue<E> {

    /**节点类的设计*/
    static class Node<E>{
        Node<E> prev;
        E value;
        Node<E> next;
        /**节点的构造函数*/
        public Node(Node<E> prev,E value,Node<E> next){
            this.prev = prev;
            this.value = value;
            this.next = next;
        }
    }

    int capacity;//容量
    int size;//有效元素个数
    Node<E> sentinel = new Node<>(null,null,null);//创建一个节点(哨兵)

    /**双端队列的构造函数*/
    public L15_LinkedListDeque(int capacity) {//构建成环
        this.capacity = capacity;
        sentinel.next = sentinel;
        sentinel.prev = sentinel;
    }
    /**头部插入
     * 核心逻辑就是找插入节点的上一个和下一个节点
     * */
    @Override
    public boolean offerFirst(E e) {
        if (isFull())
            return false;
        Node<E> a = sentinel;
        Node<E> b = sentinel.next;
        Node<E> added = new Node<>(a,e,b);
        a.next = added;
        b.prev = added;
        size++;
        return true;
    }

    @Override
    public boolean offerLast(E e) {
        if (isFull())
            return false;
        Node<E> a = sentinel.prev;
        Node<E> b = sentinel;
        Node<E> added = new Node<>(a,e,b);
        a.next = added;
        b.prev = added;
        size++;
        return true;
    }

    @Override
    public E pollFirst() {
        if (isEmpty())
            return null;
        Node<E> a = sentinel;
        Node<E> removed = sentinel.next;
        Node<E> b = removed.next;
        a.next = b;
        b.prev = a;
        size--;
        return removed.value;
    }

    @Override
    public E pollLast() {
        if (isEmpty())
            return null;
        Node<E> removed = sentinel.prev;
        Node<E> a = removed.prev ;
        Node<E> b = sentinel;
        a.next = b;
        b.prev = a;
        size--;
        return removed.value;
    }

    @Override
    public E peekFirst() {
        if (isEmpty())
            return null;
        return sentinel.next.value;
    }

    @Override
    public E peekLast() {
        if (isEmpty())
            return null;
        return sentinel.prev.value;
    }

    @Override
    public boolean isEmpty() {
        return size == capacity;
    }

    @Override
    public boolean isFull() {
        return size == 0;
    }
}

3.双端队列的数组实现

下面看一下双端队列的数组实现:

下面看一下具体的代码:

/**用数组来实现双端队列*/
public class L15_ArrayDeque<E> implements L15_TwoQueue<E>{

    E[] array;
    int head;//头指针
    int tail;//尾指针

    /**构造函数,创建出数组(也就是双端队列)*/
    public L15_ArrayDeque(int capacity) {
        array = (E[]) new Object[capacity+1];
    }

    /**处理索引越界的两个方法*/
    /**处理索引加1时的*/
    static int inc(int i, int length){
        if (i+1 >= length){
            return 0;
        }
        return i+1;
    }
    /**处理索引减1时的*/
    static int dec(int i, int length){
        if (i-1 < 0){
            return length-1;
        }
        return i-1;
    }

    @Override
    public boolean offerFirst(E e) {
        if (isFull())
            return false;
        head = dec(head,array.length);
        array[head] = e;
        return true;
    }

    @Override
    public boolean offerLast(E e) {
        if (isFull())
            return false;
        array[tail] = e;
        tail = inc(tail,array.length);
        return true;
    }

    @Override
    public E pollFirst() {
        if (isEmpty())
            return null;
        E e = array[head];
        head = inc(head,array.length);
        return e;
    }

    @Override
    public E pollLast() {
        if (isEmpty())
            return null;
        tail = dec(tail,array.length);
        return array[tail];
    }

    @Override
    public E peekFirst() {
        return array[head];
    }

    @Override
    public E peekLast() {
        return array[tail];
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

    @Override
    public boolean isFull() {
        if (tail>head)
            return tail-head == array.length-1;
        if (tail<head)
            return head-tail == 1;
        if (tail == head)
            return false;
        return true;
    }
}

用数组实现双端队列不是太清楚,主要还是用链表来实现吧。

4.优先队列无序数组实现

优先队列,就是队列中的元素具有不同优先级的一种队列。入队的操作和普通队列一样,但是出队时是优先级高的元素先出队。

下面我们来看一下优先队列的具体实现:

下面看一下具体的代码:



/**
 * 用无序数组来实现优先队列
 * */
public class L16_PriorityQueue<E extends L16_Priority> implements L8_QueueInter<E>{

    L16_Priority[] array;
    int size;

    public L16_PriorityQueue(int capacity) {
        array = new L16_Priority[capacity];
    }


    @Override
    public boolean offer(E value) {
        if(isFull())
            return false;
        array[size] = value;
        size++;
        return true;
    }

    /**返回优先级最高的索引*/
    private int selectMax(){
        int max = 0;
        for (int i = 0; i < size; i++) {
            if (array[i].priority() > array[max].priority())
                max = i;
        }
        return max;
    }

    @Override
    public E poll() {
        if (isEmpty())
            return null;
        int max = selectMax();
        E e = (E)array[max];
        remove(max);
        return e;
    }

    private void remove(int index){
        if (index < size-1){
            System.arraycopy(array,index+1,array,index,size-1-index);
        }
        size--;
    }

    @Override
    public E peek() {
        if (isEmpty())
            return null;
        int max = selectMax();
        return (E)array[max];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == array.length;
    }
}

不算难,理清思路很简单的。

优先队列基于有序数组的实现和这个类似,并且比这个更简单,就是在入队操作时要找准位置而已。

5.阻塞队列

阻塞队列涉及的其他方面的内容,当我那部分的内容更新完毕后,再回来更新这个阻塞队列的实现。

6.总结

总的来说,队列不难,关键就是抓住链表和数组的特点,掌握链表和数组的相关操作就行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L纸鸢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值