当前位置: 首页 > 知识库问答 >
问题:

索引优先级队列的混乱

李谦
2023-03-14

我已经有了优先级队列的概念,但是当涉及到索引优先级队列时,我对change(int k,Item Item)和delete(int I)等方法的实现有点困惑。

change(int k,Item Item)是将k关联的项目改为Item

delete(int i)是删除k及其关联项

public void changeKey(int i, Key key) {
        if (i < 0 || i >= maxN) throw new IndexOutOfBoundsException();
        if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
        keys[i] = key;
        swim(qp[i]);
        sink(qp[i]);
    }

public void delete(int i) {
        if (i < 0 || i >= maxN) throw new IndexOutOfBoundsException();
        if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
        int index = qp[i];
        exch(index, n--);
        swim(index);
        sink(index);
        keys[i] = null;
        qp[i] = -1;
    }

private void swim(int k) {
        while (k > 1 && greater(k/2, k)) {
            exch(k, k/2);
            k = k/2;
        }
    }

    private void sink(int k) {
        while (2*k <= n) {
            int j = 2*k;
            if (j < n && greater(j, j+1)) j++;
            if (!greater(k, j)) break;
            exch(k, j);
            k = j;
        }
    }


private int maxN;        // maximum number of elements on PQ
private int n;           // number of elements on PQ
private int[] pq;        // binary heap using 1-based indexing
private int[] qp;        // inverse of pq - qp[pq[i]] = pq[qp[i]] = i
private Key[] keys;      // keys[i] = priority of i

共有1个答案

赖诚
2023-03-14

这些是在更改键时需要在二进制堆上执行的操作。优先级队列中的每个“节点”都保留在二进制堆中。当你添加一个项目时,该项目需要被定位在正确的位置,这样‘二进制堆的规则’就不会被打破。

更改键也会发生同样的情况,您需要更改项在优先级堆中的位置,这样规则就不会被破坏(项的子项不会比它大,项的父项不会比它小)。

这个优先级队列是用一个二进制堆实现的,这意味着它是基于二叉树的,这就是为什么你可以在那些方法中看到除以2,因为它需要逐级向上/向下取项目,这是通过除以实现的(第一级有一个节点,第二级有两个节点,第三级有四个节点等,每个级别的节点数乘以2)。

这篇文章只是对一个巨大而广泛的主题的介绍,我建议阅读更多关于它的内容(特别是“heapify”部分):看看这个。

通常情况下,关键是您只有一个更改键的方法,并且它同时调用swimsink,因为前面的键可能更高或更低。通常通过两个方法来完成:dreduceKeyincreaseKey,相应地,每一个方法只调用一个-sinkswim。您的代码将这2个方法合并为1个方法,这就是它同时调用sinkswim的原因。当新键高于旧键时,这意味着它需要在堆中上升(swim);当新键低于旧键时,它需要下降(sink)。

顺便说一句,我的整个文章都假设我们使用最大堆--这意味着根节点有最大值,而他的子节点有较小的值,等等。还有一个最小堆,正好相反。

 类似资料:
  • 我需要一个优先级队列,它首先获得具有最高优先级值的项目。我当前正在使用队列库中的PriorityQueue类。但是,这个函数只先返回值最小的项。我尝试了一些很难看的解决方案,比如(sys.maxint-priority)作为优先级,但我只是想知道是否存在更优雅的解决方案。

  • 我试图实现Dijkstra算法的一个版本,以找到公共汽车从起点到终点的最短路线。不幸的是,我似乎找不到swift提供优先级队列类型的库或其他方式,所以我似乎必须自己编写代码。 话虽如此,有人能指出我做这件事的正确方向吗? 目前我的想法如下: 到目前为止这是我的代码。似乎太短太残忍了...我一定是在概念上漏掉了什么。

  • 注意:我知道可以用比较器创建优先级队列,然后重复调用Add。

  • 考虑下面的优先级类声明<代码>类优先级队列 我的想法: 我能想到的一件事是,这将强制优先级队列使用对象比较器,并且不会提供实现其自定义比较器的能力,因为类的用户可能希望基于某个不同的比较器构建队列。

  • 优先级队列(Priority Queue) 注:队列是一种特征为FIFO的数据结构,每次从队列中取出的是最早加入队列中的元素。但是,许多应用需要另一种队列,每次从队列中取出的应是具有最高优先权的元素,这种队列就是优先级队列(Priority Queue),也称为优先权队列。 1. 优先级队列的概念 1.1 优先级队列的定义 优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优

  • 我正在为Dikjstra算法做一个优先级队列。我目前在插入方法上有麻烦。我包含了整个类的代码,以防你需要更好地了解我想完成的事情。我将堆索引放在一个数组列表(heapIndex)中,堆放在另一个数组列表中。 那是我运行程序后的输出(值,优先级,堆索引)。*(-1)表示heapIndex中的空单元格。