你问一些非常有效的问题,但不幸的是他们都是那种模糊的,所以我们不能给你一个100%固体“行业标准”的答案。不过,我会尽力去超过你的观点呢:
编程风格明智的,堆是一个黑箱抽象掉优先级队列的细节
从技术上讲,优先队列是抽象接口(插入具有优先级的元素,提取最低优先级的元素),堆是具体实现(基于数组的堆,二项堆,斐波那契堆等)。
我想说的是,使用数组只是实现优先级队列的一种特殊方式。
现在,如果我们需要维护一个散列表,它将顶点键映射到堆数组中的相应索引,那么这需要在堆实现中完成,对吧?
是的,因为每次移动数组内的元素时,都需要更新散列表中的索引。
但是大多数标准堆并不提供这样的映射的散列表。
是。这可能非常烦人。
解决这个问题的另一种方法是无论任何事情,都可以将放松的顶点添加到堆中。
我想这可以工作,但我不认为我见过任何人这样做。在这里使用堆的关键是要提高性能,并在堆中添加多余的元素,这是违背它的。当然,你保留优先队列的“黑盒子”,但我不知道这是否值得。另外,额外的pop_heap操作可能会对你的渐近复杂性产生负面影响,但我不得不做数学检查。
处理这个问题的典型方法是什么?
首先,问问自己是否可以使用哑数组而不是优先级队列。 当然,现在找到O(N)中的最小元素而不是O(log n),但实现是最简单的(本身就是一个优点)。此外,如果图形密集,并且即使图形稀疏,使用数组效果也会一样高,这取决于图形的大小。
如果你确实需要一个优先级队列,那么你将不得不找到一个执行了reduceKey操作的队列。如果你找不到它,我会说它自己实现它并不坏 - 它可能比试图找到一个现有的实现然后试图使其与其他代码相适应更麻烦。
最后,我会不是建议使用真正的花式堆数据结构(如斐波那契堆)。虽然这些经常出现在教科书中作为获得最佳渐近线的方法,但实际上它们具有可怕的常数因子,与对数相比,这些常数因子是显着的。
请问我有什么不清楚。我会很乐意澄清... – batman