【问题标题】:What sorting algorithm is this, and how does it work? (If there isn't a name or well-known resource for it.)这是什么排序算法,它是如何工作的? (如果它没有名称或众所周知的资源。)
【发布时间】:2015-03-20 14:20:17
【问题描述】:

我参加 DSA 课程已经快十年了。我浏览过Wikipedia's list of sorting algorithms,但没有一个能像这个一样突出。它是优先级队列实现的一部分,似乎排序的一部分发生在推送函数 (EnQueue) 中,而另一部分发生在弹出函数 (DeQueue) 中。

这是原始的 Mathematica 代码,但由于大多数人不熟悉 Mathematica,我在每个函数下方进行了一些翻译。

EnQueue[q : queue[ar_, n_, pred_], val_] := Module[{i, j},
  If[n == Length[ar], ar = Join[ar, makeArray@Length@ar]];
  n++; ar[[n]] = val;
  i = n;
  While[True,
   j = Quotient[i, 2];
   If[j < 1 || pred[ar[[j]], ar[[i]]],
    Break[]
    ];
   ar[[{i, j}]] = {ar[[j]], ar[[i]]};
   i = j;
   ];
  q
  ]

EnQueue 函数首先检查元素的数量n 是否已达到堆的大小ar,如果是,则将堆加倍。接下来,它增加元素的数量并将新元素存储在该索引处(Mathematica 索引是从 1 开始的,而不是从 0 开始的)。然后,它将i 设置为(新元素的)该索引,并进入将j 设置为floor(i/2) 的循环,堆中间的某个元素。现在,如果j &lt; 1(据我所知,这相当于检查i == 1),或者ar[j](中间的元素)应该在@987654335之前@(新元素),然后我们打破。否则,我们交换ij处的元素,然后继续;所以在第二次迭代中,我们从i 指向中间 开始,j 指向四分之一路径。

DeQueue[queue[ar_, n_, pred_]] := 
 Module[{i, j, res = ar[[1]]},
  ar[[1]] = ar[[n]]; ar[[n]] = Null; n--;
  j = 1;
  While[j <= Quotient[n, 2],
   i = 2 j;
   If[i < n && pred[ar[[i + 1]], ar[[i]]],
    i++
    ];
   If[pred[ar[[i]], ar[[j]]],
    ar[[{i, j}]] = {ar[[j]], ar[[i]]};
    ];
   j = i];
  res]

同时,DeQueue 返回堆的前端,并将堆的后端移到前端(并取消设置后端,并减少元素的数量)。然后,从指向前面的j 开始,它进入一个循环,该循环首先将i 设置为双j如果i 在边界内(指向一个元素)但相对于下一个元素是无序的,则i 会递增。如果i 相对于j 是有序的(前面;换句话说,如果前面相对于i 顺序out),那么交换两个位置,并且j 设置为i 所在的位置。我们继续循环直到j 通过中间。

主要是上面的粗体部分我不明白。我认为它正在做的是对DeQueue 上的堆进行排序一半,并为EnQueue 中的新元素做一些排序,但我不是当然……

【问题讨论】:

  • 通常称为堆排序。见the Wikipedia article。要维护的排序属性是每个第 n 个元素与其子元素大于等于(或小于等于,取决于使用的排序),位于位置 2n2n+1

标签: algorithm sorting wolfram-mathematica binary-heap


【解决方案1】:

对我来说,入队似乎是一个最小堆例程
https://en.wikipedia.org/wiki/Heap_(data_structure)
https://en.wikibooks.org/wiki/Data_Structures/Min_and_Max_Heaps

Dequeue 移除堆的顶部元素,该元素存储在数组的第一项中,然后将其替换为数组的最后一项并将其从堆中筛选出来,每次与子交换只要一个孩子小于该项目(如果它有一个,则小于它的兄弟)。当没有更小的孩子时停止,即当项目到达堆底部或它小于它的孩子(或孩子,它只有一个)。

编辑: 'enqueue' 和 'dequeue' 表明这是一个队列。该算法是在数组中实现的二进制堆,因此这是一个优先级队列

【讨论】:

  • 啊,搜索“二进制堆”找到了一些pictorial examples,这很清楚。事实上,它似乎好像只对数组的“一半”进行排序,因为数组实际上是一棵完整树的表示,而减半/加倍索引操作实际上是在父节点和子节点之间交换元素。
猜你喜欢
  • 1970-01-01
  • 2011-02-07
  • 2010-11-21
  • 2020-08-05
  • 2011-02-25
  • 2010-10-24
  • 2014-06-16
  • 2020-11-29
相关资源
最近更新 更多