假设我们有一个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/。它是由busy_beaver在reddit.com上编写的,当时在这里讨论http://www.reddit.com/r/compsci/comments/ejaaz/is_this_equivalent_to_insertion_sort/
答案 0 :(得分:3)
您的算法在我看来与插入排序有很大不同。特别是,很容易证明插入排序正常工作(在每个阶段,第一个但是数组中的许多元素都是正确排序的;通过归纳证明;完成),而对于你的算法,似乎要证明这个更难并且它在处理过程中的任何给定点都保证了它所保证的部分排序属性并不明显。
同样,很容易证明插入排序总是最多 n 步骤(其中“步骤”我的意思是将一个元素放在正确的位置),而如果我已经理解你的算法是正确的,如果它只是向右移动一个元素(或者换句话说,有时可能不得不多次处理一个元素),它不会推进which-element-to-process-next指针,所以它是不太清楚,你的算法在最坏的情况下确实需要O(n ^ 2)时间。
答案 1 :(得分:3)
这已经有一段时间了,但是没有其他答案包含这个奇怪的算法确实对列表进行排序的证据。所以这里。
假设原始列表是 v 1 , v 2 ,..., v <子> 名词的子>。然后在 i 算法的步骤之后,我声称列表如下所示:
w 1,1 , w 1,2 ,..., w < / em> 1, r (1), v σ(1), w 2,1 ,... w 2, r (2), v < / em> σ(2), w 3,1 ...... w i , r ( i ), v σ( i < / em>),...
其中σ是 v 1 到 v i 的排序排列 w 是元素 v j j &gt; I 的。换句话说, v 1 到 v i 是按排序顺序找到的,可能与其他元素交错。此外, w j,k ≤ v j 表示每个 j 和 k 。因此,每个正确排序的元素前面都有一个(可能是空的)小于或等于它的元素块。
这是算法的运行,其中排序的元素以粗体显示,前面的元素块以斜体显示(非空)。您可以看到每个斜体元素块都小于它后面的粗体元素。
[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 < / strong>,9]
[ 1 , 4 , 2 , 6 , 7,5,0,3 , 8 ,9]
[ 1 , 2 , 4 , 6 , 7,5,0,3 , 8 ,9]
[ 1 , 2 , 4 , 6 , 5,0,3 , 7 , 8 ,9]
[ 1 , 2 , 4 , 5 , 6 , 0 ,3 , 7 , 8 ,9] [ 0 , 1 , 2 , 4 , 5 , 6 , 3 , 7 , 8 ,9]
[ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ,9]
[ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
如果我的说法属实,那么算法会排序,因为在 n 之后所有 v i 按顺序排列,并且没有剩余的元素要交错。但这个说法是真的吗?
好吧,让我们通过归纳来证明这一点。当 i = 0时,这肯定是正确的。假设 i 是真的。然后当我们运行( i + 1)st步骤时,我们选择 v i +1 并移动它进入适合的第一个位置。它肯定会通过 j ≤ i 和传递所有 v j v j &lt; v i +1 (因为这些按假设进行排序,每个元素前面只有较小或相等的元素)。它不能通过 j ≤ i 和传递任何 v j v j ≥ v i +1 ,因为有一些在 v j 之前的块中的位置。所以 v i +1 最终按照所有 v j进行排序 与 j ≤ i 。所以它在下一个 v j 之前的元素块中的某个地方结束,并且因为它最终在中> em>这样的位置,块上的条件被保留。 QED。
但是,我不会因为标记错误而责怪你的教授。如果您要发明一种以前没见过的算法,那么你可以证明它是正确的!
(算法需要一个名称,所以我建议使用 fitort ,因为我们将每个元素放在适合的第一个位置。)
答案 2 :(得分:1)
插入排序维护不变量,即当前指针左侧的元素已排序。通过将指向左侧的指针元素移动到正确的位置并推进指针,可以取得进展。
您的算法执行此操作,但有时它还会执行额外的步骤,将指针处的元素向右移动而不会使指针前进。这使得算法整体上不是插入排序,但由于相似性,您可以将其称为修改后的插入排序。
此算法平均在O( n ²)中运行,如插入排序(也像冒泡排序)。插入排序的最佳情况是已排序列表中的O( n ),对于此算法,它是O( n )但是对于反向排序列表,因为您在单个比较中找到每个元素的正确位置(但只有当你找不到合适的位置时,才会在开头留下第一个,最大的元素)。
答案 3 :(得分:0)
许多教授因为“那不是我正在寻找的答案”而臭名昭着。即使它是正确的,他们也会说它不符合他们的标准。
你正在做的事情看起来像插入排序,虽然使用删除和插入似乎只会增加不必要的复杂性。
他可能会说的是,你基本上是“拉出”价值并“将其放回”正确的位置。你的教授可能正在寻找“将价值向上(或向下)交换,直到找到正确的位置。”
它们具有相同的结果,但它们的实现方式不同。交换会更快,但不是很明显。
答案 4 :(得分:0)
我很难看到这是插入排序。使用插入排序,在每次迭代时,将在数组中正确放置一个元素。在您的解决方案中,我没有看到每次迭代时元素都“完全排序”。
插入排序算法开始: