ArrayDeque和PriorityQueue解析

一、ArrayDeque

(一)简介

ArrayDeque类是双端队列的实现类,类的继承结构如下面,继承自AbastractCollection(该类实习了部分集合通用的方法,其实现了Collection接口),其实现的接口Deque接口中定义了双端队列的主要的方法,比如从头删除,从尾部删除,获取头数据,获取尾部数据等等。

(二)主要方法

1.添加元素

addFirst(E e)在数组前面添加元素 如果添加元素为空返回异常
offerFirst(E e)在数组前面添加元素,并返回是否添加成功 ,如果添加元素为空返回异常
addLast(E e)在数组后面添加元素 如果添加元素为空返回异常
offerLast(E e) 在数组后天添加元素, 并返回是否添加成功 如果添加元素为空返回异常

2.删除元素

removeFirst()删除第一个元素,并返回删除元素的值,如果元素为null,将抛出异常
pollFirst()删除第一个元素,并返回删除元素的值,如果元素为null,将返回null
removeLast()删除最后一个元素,并返回删除元素的值,如果为null,将抛出异常
pollLast()删除最后一个元素,并返回删除元素的值,如果为null,将返回null
removeFirstOccurrence(Object o) 删除第一次出现的指定元素
removeLastOccurrence(Object o) 删除最后一次出现的指定元素

3.获取元素

getFirst() 获取第一个元素,如果没有将抛出异常
getLast() 获取最后一个元素,如果没有将抛出异常
peekFirst(): 获取第一个元素,但是不移除;
peekLast(): 获取最后一个元素,但是不移除;

4.普通队列操作 尾部添加 头部删除 获取元素也是获取头部第一个元素返回值

add(E e) 在队列尾部添加一个元素
offer(E e) 在队列尾部添加一个元素,并返回是否成功
remove() 删除队列中第一个元素,并返回该元素的值,如果元素为null,将抛出异常(其实底层调用的是removeFirst())
poll() 删除队列中第一个元素,并返回该元素的值,如果元素为null,将返回null(其实调用的是pollFirst())
element() 获取第一个元素,如果没有将抛出异常
peek() 获取第一个元素,如果返回null

由于ArrayDeque可以从两端都可以添加和删除元素所以可以将其当作栈来使用
5.栈操作 头部添加 头删除

push(E e) 栈顶添加一个元素
pop(E e) 移除栈顶元素,如果栈顶没有元素将抛出异常

6.其他

size() 获取队列中元素个数
isEmpty() 判断队列是否为空
iterator() 迭代器,从前向后迭代
descendingIterator() 迭代器,从后向前迭代
contain(Object o) 判断队列中是否存在该元素
toArray() 转成数组
clear() 清空队列
clone() 克隆(复制)一个新的队列

(三)方法实现

1.底层维护一个数组,初始容量为16,定义一个头指针和尾指针。

    private E[] elements;
    private int head;
    private int tail;
    private final int INIT_CAPACITY = 16;

2.头插法

public boolean offerFirst(E e) {   //在数组头面添加元素
        if (e == null) {
            throw new NullPointerException();
        }
        head = (head - 1) & (elements.length - 1); //要实现环形的操作必须保证length是2的幂
        elements[head] = e;
        if (tail == head) {
            //扩容
        }
        return true;
    }

3.扩容

 private void grow() {
        int n = elements.length;
        int newCapacity = n << 1; //正整数的范围    0000 0001    int
        if (newCapacity < 0) {
            throw new IllegalStateException("Sorry,deque too big");
        }
        Object[] a = new Object[newCapacity];
        //将原数组中数据要拷贝到新数组中
        int r = n - head;  //第一次拷贝的元素的个数
        System.arraycopy(elements, head, a, 0, r);
        System.arraycopy(elements, 0, a, r, head);
        elements = (E[]) a;
        head = 0;
        tail = n;
    }

二、PriorityQueue

(一) 简介

优先级队列像普通队列一样,拥有队头和队尾,但队列中的元素是按照自然排序或者指定的比较器排序的。这一特性在实际中有很多应用,比如对于重要客户或紧急的消息可以优先处理。自 JDK 1.5 起,Java 容器类库中提供了优先级队列的工具 — PriorityQueue。

(二)PriorityQueue 原理

PriorityQueue 是基于最小堆原理实现。最小堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节的值。

(三)方法实现

1.offer方法

public boolean offer(E e){
        if(e==null)
            throw new NullPointerException();
        int i=size;
        if(i>=queue.length)
            grow();//扩容
        size = i + 1;
        if (i == 0)
            queue[0] = e;
        else
            siftUp(i, e);
        return true;
    }

2.向下调整(以外比较器为例)

private void siftUpUsingComparator(int i, E e) {
        while(i>0){
            int parent=(i-1)>>1;
            if(comparator.compare((E)queue[parent],e)<=0){
                break;
            }
            queue[i]=queue[parent];
            i=parent;
        }
        queue[i]=e;
    }

3.扩容(容量小于64选用3/2倍扩容法,大于64选用2倍+2)

private void grow() {
        int oldCapcity =queue.length;
        int newCapcity=oldCapcity>64?(oldCapcity<<1+2):(oldCapcity+oldCapcity>>1);
        queue=Arrays.copyOf(queue,newCapcity);
    }

4.删除

public boolean remove(Object o){
        int i=indexOf(o);
        if(i==-1)
            return false;
        int s=--size;
        if(i==s){
            queue[s]=null;
            return true;
        }
        E moved=(E)queue[s];//删除最后一个元素
        queue[s]=null;
        siftDown(i,moved);
        if(queue[i]==moved){//没有向下调整,所以需要向上调整
            siftUp(i,moved);
        }
        return true;
    }

5.向下调整法(以外比较器为例)

private void siftDownUsingComparator(int i, E x) {
        int half=size>>1;
        while(i<half){
            int left=(i<<1)+1;
            Object L=queue[left];
            int right=left+1;
            Object R=queue[right];
            if(right<size){
                if(comparator.compare((E)L,(E)R)>0){
                    left=right;
                    L=R;
                }

            }
            if(comparator.compare(x,(E)L)<=0){
                break;
            }
            queue[i]=L;
            i=left;
        }
        queue[i]=x;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值