使用排序列表实现优先级队列

时间:2012-09-17 15:42:38

标签: java

刚刚完成用LinkedList编写此实现。我知道这是一个初学者实现。肯定有很多错误。我只是想知道是否有人可以告诉我insert(K key, V value)方法的最坏情况的成本。我应该留在O(n)吗?

使用addLast()中的getLast()LinkedList方法进行了编辑,并使用ListIterator代替Iterator

公共类SortedListPriorityQueue实现PriorityQueue {

protected List<Entry<K,V>> entries;
protected Comparator<K> c;

private static class MyEntry<K,V> implements Entry<K,V>{

    protected K key;
    protected V value;

    public MyEntry(K key, V value){
        this.key = key;
        this.value = value;
    }

    @Override
    public K getKey() {
        return this.key;
    }

    @Override
    public V getValue() {
        return this.value;
    }
}


/**
 * Crea la coda con il comparatore DefaultComparator
 */
public SortedListPriorityQueue() {
    entries = new LinkedList<Entry<K,V>>();
    c = new DefaultComparator<K>();
}

/* Utilizza un comparatore specifico
 public SortedListPriorityQueue(Comparator<K> comp) {}
*/

@Override
public int size() {
    return entries.size();
}

@Override
public boolean isEmpty() {
    return entries.isEmpty();
}

@Override
public Entry<K, V> min() {
    if(entries.isEmpty()) throw new RuntimeException("Priority queue is empty");
    else return entries.get(0);
}

@Override
public Entry<K, V> removeMin() {
    if(entries.isEmpty()) throw new RuntimeException("Priority queue is empty");
    else return entries.remove(0);

}

@Override
public Entry<K, V> insert(K key, V value) {
    Entry<K,V> new_entry = new MyEntry<K,V>(key, value);

    insertEntry(new_entry);
    return new_entry;
}

private void insertEntry(Entry<K, V> e) {
    //caso base1: lista vuota
    if(entries.isEmpty()){
        entries.add(e);
        return;
    }

    // caso base2: inserisce alla fine della lista
    else if(c.compare(e.getKey(), ((LinkedList<Entry<K, V>>) entries).getLast().getKey()) > 0){
        ((LinkedList<Entry<K,V>>) entries).addLast(e);
        return;
    }

    ListIterator<Entry<K,V>> it = entries.listIterator();
    Entry<K,V> current = null;

    while(it.hasNext()){
        current = it.next();
        if(c.compare(e.getKey(), current.getKey()) < 0){
            it.add(e);
            return;
        }
    }
}

}

4 个答案:

答案 0 :(得分:2)

是的,您的最坏情况插入时间是O(n) - 插入列表末尾附近的内容。您花费O(n)时间来查找正确的索引,然后在O(n)LinkedList.add时间插入它。

答案 1 :(得分:1)

优先级队列可以使用堆实现

实现O(log n)插入

答案 2 :(得分:0)

最坏情况的成本是线性的,它取决于您拥有的条目数量-1,因为它必须在列表中的最后一个元素之前插入。所以它是O(n)。

答案 3 :(得分:0)

是的,它是O(n)

但请注意,n的常数乘数并非最佳,因为get(int)的{​​{1}}和add(int, T)也是LinkedList,但您可以替换他们使用O(n)次操作 - O(1)getLast()addLast()。也就是说,现在需要ListIterator.add()个步骤来查找新条目的位置,并O(n)步骤实际插入它,但您可以修改您的实现以在O(n)中找到一个位置并插入在O(n)

这样的替换不会改变算法的渐近复杂度(它仍然是O(1)),但它会改善算法的典型实际性能。

当然,对于实际应用,最好使用基于堆的实现(例如内置的实现)来提供O(n)插入和删除。