Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 使用多个堆的Heapsort_Algorithm_Sorting_Heapsort - Fatal编程技术网

Algorithm 使用多个堆的Heapsort

Algorithm 使用多个堆的Heapsort,algorithm,sorting,heapsort,Algorithm,Sorting,Heapsort,我发现了一个变体Heapsort,它同时使用多个堆。该解决方案提出,与传统的Heapsort算法不同,在每次交换之后,我们进行另一次siftdown以将当前堆中的最高值带到根,我们可以做一些其他事情。然而,他们所说的“其他事物”究竟是什么意思,我无法理解 例如,有一次,他们说我们暂时“忘记”根的存在。这肯定意味着我们目前正在暂停最高元素与堆的最后一个元素的交换。然而,就在几行之后,他们说,到目前为止,在堆的已排序部分中已经传输了两个元素。,这与交换尚未完成的主张背道而驰。同样在第97页的图中,值

我发现了一个变体
Heapsort
,它同时使用多个堆。该解决方案提出,与传统的
Heapsort
算法不同,在每次交换之后,我们进行另一次
siftdown
以将当前堆中的最高值带到根,我们可以做一些其他事情。然而,他们所说的“其他事物”究竟是什么意思,我无法理解

例如,有一次,他们说我们暂时“忘记”根的存在。这肯定意味着我们目前正在暂停最高元素与堆的最后一个元素的交换。然而,就在几行之后,他们说,到目前为止,在堆的已排序部分中已经传输了两个元素。,这与交换尚未完成的主张背道而驰。同样在第97页的图中,值为1的节点丢失了,我不知道怎么做

有谁能告诉我作者到底想表达什么,以及它有多值得?

(你问的那句话在第2.3节,所以我将解释第2.3节中提出的heapsort的变体:)

当作者说我们“忘记”根的存在时,这并不意味着他们在拖延最高元素的交换。交换已完成,但它们会暂时延迟重建堆。将最高的元素交换到根位置后,它们将比较2个子范围的根,并将其中一个与下一个最高的元素交换。然后,在进行2次交换(而不是1次)后,它们重建堆

然后,他们在第3节和第4节中进一步阐述了这一想法,并提出了另一种heapsort变体,它使用多个堆

如何在一个数组中保持多个堆?(为了使其具体化,让我们讨论两个堆。)那么,如何保持单个堆?根在索引0处,它的子节点在1和2处,然后左子节点的子节点在3和4处,等等,对吗

要将2个堆放在一个数组中,请将2个根保持在0和1。第一根的子代在2和3,然后第二根的子代在4和5。。。有了这样的安排,通过对索引执行简单的算术运算,仍然可以在树上上下导航

标准heapsort重复两个步骤:将根目录与“heap”区域中的最后一个元素交换,然后
siftDown
重建堆。此heapsort重复以下3个步骤:比较两个根以查看哪个根更大,将该根与“heap”区域中的最后一个元素交换,然后在适当的堆上调用
siftDown

这需要在每个步骤中进行额外的比较,但是
siftDown
操作在稍微浅一点的堆上工作,这节省了不止一次比较。

(您询问的行在第2.3节中,因此我将解释第2.3节中提出的heapsort的变化:)

当作者说我们“忘记”根的存在时,这并不意味着他们在拖延最高元素的交换。交换已完成,但它们会暂时延迟重建堆。将最高的元素交换到根位置后,它们将比较2个子范围的根,并将其中一个与下一个最高的元素交换。然后,在进行2次交换(而不是1次)后,它们重建堆

然后,他们在第3节和第4节中进一步阐述了这一想法,并提出了另一种heapsort变体,它使用多个堆

如何在一个数组中保持多个堆?(为了使其具体化,让我们讨论两个堆。)那么,如何保持单个堆?根在索引0处,它的子节点在1和2处,然后左子节点的子节点在3和4处,等等,对吗

要将2个堆放在一个数组中,请将2个根保持在0和1。第一根的子代在2和3,然后第二根的子代在4和5。。。有了这样的安排,通过对索引执行简单的算术运算,仍然可以在树上上下导航

标准heapsort重复两个步骤:将根目录与“heap”区域中的最后一个元素交换,然后
siftDown
重建堆。此heapsort重复以下3个步骤:比较两个根以查看哪个根更大,将该根与“heap”区域中的最后一个元素交换,然后在适当的堆上调用
siftDown


这需要在每一步进行额外的比较,但是
siftDown
操作在稍微浅一点的堆上工作,这节省了不止一次比较。

。交换后,我知道当前根的左或右节点(交换时,可能比其中任何一个都小)是行中的下一个元素(因为两个节点中的一个必须是第二高的,尽管第三高的可能在深处)。因此,我不必再使用另一个
siftdown
将这两个节点中的一个推到顶部,而只需在它们之间进行比较,将较高的节点与堆中当前的最后一个元素交换。也就是说,根据siftdown,我交换了2个元素,对吗?所以
siftdown
s的数量大约减少了一半?是的。完全正确。(如果这回答了您的问题,我们将不胜感激。)但这几乎不能降低复杂性,它仍然是
O(nlog n)
。这篇文章说的更多,比如区分一个表达式以获得最佳堆数,等等。这个解决方案相当简单,我认为这不是对这篇文章的正确解释。这篇文章没有说这会降低堆的复杂性。这是不可能的,因为O(n logn)对于基于比较的排序是最优的。它所做的(据推测)是减少使用的比较/交换的数量。这并不意味着减少复杂性,而是意味着减少常数因子