【问题标题】:Is this equivalent to insertion sort?这相当于插入排序吗?
【发布时间】:2011-07-19 07:40:30
【问题描述】:

假设我们有一个索引为 0 的序列 S,取 S[0] 并将其插入 S 中下一个值高于 S[0] 且前一个值低于 S[0] 的位置。形式上,S[i] 应该放在 S[i-1]

在列表中这样工作:

Sorting [2, 8, 5, 4, 7, 0, 6, 1, 10, 3, 9]
[2, 8, 5, 4, 7, 0, 6, 1, 10, 3, 9]
[2, 8, 5, 4, 7, 0, 6, 1, 10, 3, 9]
[2, 5, 4, 7, 0, 6, 1, 8, 10, 3, 9]
[2, 4, 5, 7, 0, 6, 1, 8, 10, 3, 9]
[2, 4, 5, 7, 0, 6, 1, 8, 10, 3, 9]
[2, 4, 5, 0, 6, 1, 7, 8, 10, 3, 9]
[0, 2, 4, 5, 6, 1, 7, 8, 10, 3, 9]
[0, 2, 4, 5, 1, 6, 7, 8, 10, 3, 9]
[0, 1, 2, 4, 5, 6, 7, 8, 10, 3, 9]
[0, 1, 2, 4, 5, 6, 7, 8, 3, 9, 10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Got [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

由于每次将元素插入列表时,列表中的 (n-1) 个数字可能会被移动,我们必须执行 n 次,算法应该在 O(n^2) 时间内运行。

我有一个 Python 实现,但不知何故我放错了地方。稍后我会尝试再次编写它,但实现起来有点棘手。有什么想法吗?

Python 实现在这里:http://dpaste.com/hold/522232/。它是由 reddit.com 的 busy_beaver 写的,在这里讨论http://www.reddit.com/r/compsci/comments/ejaaz/is_this_equivalent_to_insertion_sort/

【问题讨论】:

  • 如果有多个可能的位置,你会选择哪一个?
  • @aaz 第一个找到。
  • 这不是插入排序。 IS 的一个基本特征是,经过 M 次迭代,前 M 个元素是有序的。您对算法的描述提供了这一点,尽管方式非常复杂。

标签: algorithm insertion-sort


【解决方案1】:

这个问题已经有一段时间了,但其他答案都没有证明这个奇怪的算法确实对列表进行了排序。就这样吧。

假设原来的列表是v1, v2, ..., vn。然后在算法的 i 个步骤之后,我声称列表如下所示:

w1,1, w1,2, ..., w1,r(1),vσ(1),w em>2,1, ... w2,r(2), vσ(2), w3,1 ... ... wi,r(i), vσ(i), ...

其中 σ 是 v1vi 的排序排列w 是元素 vjj > i。换句话说,v1vi 是按排序顺序找到的,可能与其他元素交错。而且,wj,kvj sub> 对于每个 jk。因此,每个正确排序的元素前面都有一个(可能为空的)小于或等于它的元素块。

这是算法的运行,已排序的元素以粗体显示,前面的元素块以斜体显示(其中非空)。可以看到,每块斜体元素都小于后面的粗体元素。

[4, 8, 6, 1, 2, 7, 5, 0, 3, 9]
[4, 8, 6, 1, 2, 7, 5, 0, 3, 9]
[4, 6, 1, 2, 7, 5, 0, 3, 8, 9]
[4, 1, 2, 6, 7, 5, 0, 3, 8, 9]
[14267、5、0、3, 8, 9]
[12467、5、0、3, 8, 9]
[1, 2, 4, 6, 5, 0, 3, 78、9]
[124560 , 3, 7, 8, 9]
[012456 378、9]
[012345 678、9]
[012345 6789]

如果我的说法是真的,那么算法会排序,因为在 n 步骤之后所有 vi是有序的,并且没有剩余的元素要交错。但这种说法真的是真的吗?

好吧,让我们通过归纳来证明它。当 i = 0 时肯定是真的。假设 i 是真的。然后当我们运行 (i + 1) 步骤时,我们选择 vi+1 并移动它到它适合的第一个位置。它肯定会通过所有 vjji vjvi+1(因为这些是按假设排序,每个前面都只有较小或相等的元素)。它不能通过任何 vjji vjvi+1,因为有一些在 vj 之前的块中它适合的位置。所以 vi+1 最终对所有 vj em>ji。所以它在下一个 vj 之前的元素块中的某个位置结束,因为它在 first em> 这样的位置,块上的条件被保留。 QED。

不过,我不怪你的教授把它打错了。如果您要发明一种前所未见的算法,则由 来证明它是正确的!

(算法需要一个名字,所以我建议fitsort,因为我们把每个元素放在最适合它的位置。)

【讨论】:

  • 太棒了。我想知道新的排序算法多久发明一次。
【解决方案2】:

插入排序保持对当前指针左侧的元素进行排序的不变性。通过将指针处的元素向左移动到正确的位置并推进指针来取得进展。

您的算法会执行此操作,但有时它还会执行一个额外的步骤,即在不推进指针的情况下将指针处的元素向右移动。这使得算法作为一个整体不是插入排序,尽管由于相似性,您可以将其称为修改后的插入排序。

此算法平均运行时间为 O(n²),类似于插入排序(也类似于冒泡排序)。插入排序的最佳情况是 O(n) 在已经排序的列表上,对于这个算法它是 O(n) 但对于反向排序的列表,因为你在单个比较中为每个元素找到正确的位置(但前提是当您找不到合适的位置时,将第一个最大的元素留在开头)。

【讨论】:

  • 或修改冒泡排序或修改卵石排序。
【解决方案3】:

我很难看出这是插入排序。使用插入排序,在每次迭代中,将在数组中正确放置一个元素。在您的解决方案中,我没有看到元素在每次迭代时都被“完全排序”。

插入排序算法开始:

  1. 让 pos = 0
  2. 如果 pos == arraysize 则返回
  3. 从 pos 中找出剩余数组中最小的元素,并与位置 pos 的元素交换
  4. 位置++
  5. 转到 2

【讨论】:

  • 你已经描述了选择排序。
【解决方案4】:

在我看来,您的算法与插入排序非常不同。特别是,很容易证明插入排序正确工作(在每个阶段,数组中的第一个但许多元素都被正确排序;通过归纳证明;完成),而对于您的算法来说,证明这一点似乎要困难得多而且它在处理过程中的任何给定点都保证了哪些部分排序属性并不明显。

同样,很容易证明插入排序总是最多执行 n 步(这里的“一步”是指将一个元素放在正确的位置),而如果我理解的话您的算法正确,如果它只是将一个元素向右移动,它不会推进 which-element-to-process-next 指针(或者,换句话说,它有时可能需要多次处理一个元素)所以它是不太清楚你的算法在最坏的情况下确实需要 O(n^2) 时间。

【讨论】:

    【解决方案5】:

    许多教授因“这不是我要寻找的答案”错误而臭名昭著。即使它是正确的,他们也会说它不符合他们的标准。

    您所做的似乎是插入排序,尽管使用删除和插入似乎只会增加不必要的复杂性。

    他可能会说,您实际上是在“拉出”价值并将其“放回”正确的位置。您的教授可能正在寻找“向上(或向下)交换值,直到找到正确的位置。”

    它们的结果相同,但实现方式不同。交换会更快,但不是很明显。

    【讨论】:

    • 请详细说明您如何看待这是插入排序?
    猜你喜欢
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多