【问题标题】:CLRS Insertion Sort ImplmentationCLRS 插入排序实现
【发布时间】:2016-01-19 17:19:29
【问题描述】:

我正在检查 CLRS 中的插入排序算法。我不确定哪个是正确的实现 -

来自 CLRS 的算法 -

实施 1:

def Insertion_sort():
list = [3,5,1,7,2,4]
for j in xrange(1,len(list)):
    i = j-1
    while i>=0 and list[i] > list[j]:
        swap(list, i, j)
        j = i
        i = i-1

实施 2:

def Insertion_sort2():
list = [3,5,1,7,2,4]
for j in range(1,len(list)):
    i = j-1;
    while i>=0 and list[i]>list[j]:
        i = i-1;
    swap(list, i+1, j)

谢谢

【问题讨论】:

  • 你试过了吗? (在 CLRS 算法中你在哪里看到swap?)
  • 他们都为我工作。
  • @user3886450:为清楚起见,要使排序功能起作用,它必须对所有输入起作用。在[3, 5, 1, 7, 2, 4] 的各种前缀上尝试第二个(如果您愿意,可以将4 更改为6),您会发现它恰好导致这个特殊情况只是偶然的。 (或者,可以说是不合时宜的,因为结果是隐藏了一个明显的错误。)
  • 您的示例都不能使用javacg++ 编译。
  • @stackoverflowuser2010:这并不奇怪,因为它们是用 Python 编写的。

标签: algorithm insertion-sort clrs


【解决方案1】:

两个提议的函数实际上都没有重现 CLRS 中提出的算法。

CLRS 算法中的第 5 行到第 8 行中的代码对以索引 j 结尾的列表的子序列进行旋转。这会将索引j 处的值插入到列表前缀的正确位置。

你的第一个函数做同样的事情,但不是做一个轮换,而是做一系列的交换。轮换效率更高,因为它只修改每个列表项一次而不是两次。

您的第二个函数只进行了一次交换,它将元素 j 处的值移动到正确的位置,但不保留列表前缀其余部分的顺序。所以它要快得多,但会产生不正确的结果。 (它碰巧用您的测试向量产生一个排序输出的事实很有趣,但是如果您查看每个插入点的连续前缀,您会发现它并没有真正起作用。尝试仅对[2, 3, 1] 进行排序,例如。)

【讨论】:

    【解决方案2】:

    两者都是正确的,并且都在 O(n^2) 时间内运行,但第二个实现更好,因为您只对列表的每个元素执行 1 次交换,而对于第一个实现,您执行 O(n^2)掉期。第一个实现将异位数字与下一个数字交换,直到该数字位于正确的位置,而第二个实现在将数字交换到其最终正确位置之前找到异位数字的正确索引。尽管交换是 O(1) 时间,但它们比简单地减少一个数字需要更长的时间。

    【讨论】:

    • 也许你应该在更广泛的输入选择上尝试第二个。显然它不起作用,因为一次交换不足以将值插入到排序列表中。
    • 你在说什么?它确实有效。一次交换就足够了。
    • 用输入向量[3,5,1,7,2,6]试试。或者只是[3, 5, 1]。它与[3, 5, 1, 7, 2, 4] 一起工作的事实纯属运气。 (以及如何通过一次交换将[3, 5, 1] 转换为[1, 3, 5]?显然,一次交换是不够的。一次轮换 就足够了。)
    猜你喜欢
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    相关资源
    最近更新 更多