我正在阅读"Insertion Sort is O(nlogn) by Michael A. Bender , Martín Farach-Colton , Miguel Mosteiro",我不太明白该算法的工作原理以及如何在Wikipedia的帮助下实现该算法。以下是从原始文章中提取的算法的描述。
1)设A是要排序的n元素数组。这些元素插入一个 随机顺序的时间到大小为(1 +ε)n的排序数组S.
所以第一步是创建大小(1 +ε)n的数组。设ε= 1,然后我需要创建一个大小比原始数组大两倍的数组。
2)插入按log(n)轮进行,如下所述。 每一轮将插入S中的元素数量加倍,并将元素所在的S前缀加倍。
据我所知,外循环将循环log(n)时间。每一轮,我需要将A(原始数组)中的元素数量加倍到S数组。 我真正理解的是“S的前缀加倍。
3)具体地,当插入元素2 i 并且元素被重新平衡时,round i th 结束。在重新平衡之前,2 i 元素位于第一个(1 +ε)2 i 位置。 重新平衡将它们移动到第一个(2 +2ε)2 i 位置,传播 元素尽可能均匀。我们称2 +2ε扩展因子。
据我所知,每一轮,我们都会做“重新平衡”。 “rebalance”会将原始元素均匀地分布在S数组中,以便在元素之间留下一些空隙。传播元素的公式是: k = i *(1 +ε)其中 i 是旧索引, k < / em>是一个新索引。
4)在第i轮 th 内插入2 i-1 插入元素 蛮力方式:搜索要插入的元素的目标位置 二元搜索(在S中的2个 i-1 支持位置中)和移动元素 更高等级为新元素腾出空间。并非所有元素都更高 需要移动等级,只有相邻数组位置的等级直到最近 差距被发现。
这部分展示了如何将每个元素插入到S数组中。首先,使用二进制搜索来搜索元素应该属于的位置。然后,转移更高的等级直到它达到差距。
这是我理解的算法的翻译(其中A是数组到排序,数组以索引1开始):
def LibrarySort(A) n ← length(A) S ← array of size (1 + ε) * n for i ← 1 to n S[i] = null for i ← 1 to floor(log(n) + 1) for j ← 2i - 1 to 2i index = binarysearch(S, A[j]) insert(S, A[j], index) rebalance()
然后对于insertion()函数需要3个参数:array,要插入的项和location。
def insert(S, item, index)
if S[index] != null
tmp ← S[index]
i ← index + 1
while i <= length(S) and S[i] != null
swap(tmp, S[i])
i++
S[index] ← item
问题
答案 0 :(得分:1)
Ad“将S的前缀加倍”:数组(内存)在开头分配一次,大小为(1 + ε) n ,其中< em> n 是要排序的元素总数。但是元素是逐渐添加的,并且随着它们的添加,它们不会遍布整个数组,而只是它的一些前缀。当 m 元素重新平衡时,它们分布在数组的第一个(1 + ε) m 元素中。这是前缀。当 m 加倍时,(1 + ε) m 也是如此。
广告正确性:我看到一个小错误:
传播元素的公式是:k = i *(1 +ε)其中i是旧索引,k是新索引。
引用的描述没有说明公式是什么,但它不能是这个。因为这会将长度为 m 的数组映射到长度(1 + ε) m ,但描述说您要映射长度数组(1 + ε) m 到长度为2的数组(1 + ε) m 。
一个简单的表达式是 k = 2 i 其中 i 是旧索引,但那不会均匀地分散元素。要均匀地分布元素,公式为 k =(2 + 2 ε) i ,但 i 是index 排除任何差距。