手写数据结构之优先有序队列

前面我用堆写了一个优先队列,可以保证优先级高的先执行,但不能保证同等优先级的有序。java JDK的PriorityBlockingQueue也是用堆实现的优先队列。

场景:如果有1~9个会员等级进行排队购买,首先保证高等级的进行优先购买,同等级的有序排队。那么这个场景采用普通的优先队列就不能满足了。

理论方案:靠普通堆是实现不了的,除非你在构建堆的时候进行额外处理,强行保证它同等级的有序,那这个还不如写排序来的实在。还是以堆数据结构作为基础,实现优先功能,接下来就是要保证同等级别的有序了,这个功能交给链表实现。先将传过来的对象插入堆中,然后堆对象的关键字放入散列函数进行求值,获得在散列表里的位置,散列表装的就是链表了,然后把对象插入到链表最后,就将这个对象进行了一个排序。所以反过来获取第一个要购物的对象就是:堆的第一个位置始终是优先级最高的对象(此对象在优先级里可能不是第一个),然后对这个对象进行散列求值得到散列表的位置,获取散列表里链表的第一个元素就是真正实际第一个要购物的对象。

时间复杂度还是很快的:O(logn)+O(1)+O(1),不足就是对象花费了双倍空间。

java代码实现:

package com.tczs.heap;

public abstract class AbstractCompare<T> implements Comparable<T>{

    protected int key;

    public abstract int getKey();

    public abstract void setKey(int key);

    @Override
    public int compareTo(T o){
        if(o instanceof AbstractCompare){
            AbstractCompare obj = (AbstractCompare) o;
            if(key > obj.key)
                return 1;
            else if(key < obj.key)
                return -1;
            else
                return 0;
        }else
            throw new IllegalArgumentException();
    }
}
package com.tczs.heap;

import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class PriorityOrderlyBlockingQueue<T extends AbstractCompare<T>> {

    private Object[] array; //二叉堆数组
    private int capacity = 16;
    private int hashTableLength = 20; //确保这个值比你的优先级种类数量大
    private int length;
    private int index;
    private NodeValue[] nodeArray; //链表数组
    private final ReentrantLock lock;
    private final Condition notEmpty;
    private static final int MAXIMUM_CAPACITY = Integer.MAX_VALUE;


    public PriorityOrderlyBlockingQueue(int initialCapacity,int hashTableLength){
        if(initialCapacity > 7)
            this.capacity = initialCapacity;
        if(hashTableLength > 7)
            this.hashTableLength = hashTableLength;
        nodeArray = new NodeValue[this.hashTableLength];
        array = new Object[this.capacity];
        lock = new ReentrantLock();
        notEmpty = lock.newCondition();
    }

    public PriorityOrderlyBlockingQueue(int initialCapacity){
        this(initialCapacity,0);
    }

    public PriorityOrderlyBlockingQueue(){
        this(0,0);
    }

    public int size(){
        return this.length;
    }

    /**
     * 获取最小元素
     * @return
     */
    public T getMin(){
        return get(1);
    }

    public T get(int index){
        return array==null ? null:(T)array[index];
    }

    public void put(T element){
        ReentrantLock lock = this.lock;
        lock.lock();
        try{
            buildHeap(element);
            hashInsertElement(element);
            notEmpty.signal();
        }finally {
            lock.unlock();
        }
    }

    /**
     * 构建二叉堆(插入元素)
     * @param element
     */
    public void buildHeap(T element){
        if(element == null)
            throw new NullPointerException("element is null");
        if(++index == capacity){
            capacity = Math.min(MAXIMUM_CAPACITY,capacity<<1);
            array = Arrays.copyOf(array,capacity);
        }
        array[index] = element;
        fixedInsertArray(this.index);
        length++;
    }

    private void fixedInsertArray(int index ){
        while(index != 1){
            T current = get(index);
            if(current == null)
                break;
            T parent = get(index/2);
            if (compare(current, parent) < 0) {
                array[index / 2] = current;
                array[index] = parent;
            }else
                break;
            index = index/2;
        }
    }

    private void hashInsertElement(T element){
        int index = hash(element);
        NodeValue nodeValue = nodeArray[index];
        if(nodeValue == null){
            Node<T> newNode = new Node<T>(element);
            nodeValue = new NodeValue<>(newNode,newNode);
            nodeArray[index] = nodeValue;
        }else {
            Node<T> newNode = new Node<T>(element);
            Node lastNode = nodeValue.lastNode;
            lastNode.next = newNode;
            nodeValue.lastNode = newNode;
        }
    }

    private int hash(T element){
        return element.getKey() % hashTableLength;
    }

    public T peek(){
        ReentrantLock lock = this.lock;
        lock.lock();
        try{
            if(this.length == 0)
                return null;
            else {
                T element = getMin();
                int index = hash(element);
                NodeValue nodeValue = nodeArray[index];
                if(nodeValue == null)
                    throw new IllegalStateException("hash error");
                else {
                    Node<T> node = nodeValue.firstNode;
                    return node.element;
                }
            }
        }finally {
            lock.unlock();
        }
    }

    public T take() throws InterruptedException {
        ReentrantLock lock = this.lock;
        lock.lock();
        try{
            while (this.length == 0)
                notEmpty.await();
            T element = deleteMin(); //删除二叉堆上的
            int index = hash(element);
            NodeValue<T> nodeValue = nodeArray[index];
            if(nodeValue == null)
                throw new IllegalStateException("hash error");
            else {
                Node<T> firstNode = nodeValue.firstNode;
                T result = firstNode.element;
                firstNode.element = null;
                Node next = firstNode.next;
                if(next == null)
                    nodeArray[index] = null;
                else {
                    firstNode.next = null;
                    nodeValue.firstNode = next;
                }
                return result;
            }
        }finally {
            lock.unlock();
        }
    }

    /**
     * 删除最小元素
     * @return
     */
    public T deleteMin(){
        if(array == null)
            return null;
        T result = get(1);
        if(length == 1)
            array[1] = null;
        else if(length == 2){
            array[1] = array[2];
            array[2] = null;
        }else
            deleteM();
        index--;
        length--;
        return result;
    }

    private void deleteM(){
        int index = 1;
        int leftIndex = index<<1;
        T left;
        while((left=get(leftIndex)) != null){
            T right = get(leftIndex+1);
            if(right == null){
                array[index] = left;
                array[leftIndex] = null;
                break;
            }
            if(compare(left,right) < 0){
                array[index] = left;
                array[leftIndex] = null;
            }else {
                array[index] = right;
                leftIndex = leftIndex+1;
                array[leftIndex] = null;
            }
            if(leftIndex<<1 >= capacity || get(leftIndex<<1) == null)
                break;
            index = leftIndex;
            leftIndex = index<<1;
        }
        array[leftIndex] = array[this.index];
        array[this.index] = null;
        fixedInsertArray(leftIndex);
    }

    private int compare(T current,T parent){
        return current.compareTo(parent);
    }

    class NodeValue<T>{
        Node<T> firstNode;
        Node<T> lastNode;
        NodeValue(Node<T> firstNode,Node<T> lastNode){
            this.firstNode = firstNode;
            this.lastNode = lastNode;
        }
    }

    class Node<T>{
        T element;
        Node<T> next;
        Node(T element){
            this.element = element;
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

3wtczs93点抗母

钱癌晚期

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

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

打赏作者

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

抵扣说明:

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

余额充值