7

当我发现有一种称为循环排序的算法使内存写入次数最少时,我正在浏览互联网。但是我无法在任何地方找到该算法。如何检测循环中是否存在循环大批?谁能给这个算法一个完整的解释?

4

2 回答 2

19

循环排序算法的动机是一种称为循环分解的东西。循环分解最好用例子来解释。假设你有这个数组:

4 3 0 1 2

让我们想象一下,我们有这个按排序顺序排列的序列,如下所示:

0 1 2 3 4

我们如何对这个排序后的数组进行洗牌才能得到洗牌后的版本?好吧,让我们并排放置它们:

0 1 2 3 4
4 3 0 1 2

让我们从头开始。请注意,数字 0 被交换到 2 最初持有的位置。反过来,数字 2 被交换到 4 最初持有的位置。最后,4 被交换到 0 最初持有的位置。换句话说,元素 0、2 和 4 都向前循环了一个位置。这留下了数字 1 和 3。请注意,1 交换到 3 所在的位置,3 交换到 1 所在的位置。换句话说,元素 1 和 3 向前循环了一个位置。

作为上述观察的结果,我们可以说序列 4 3 0 1 2 具有循环分解 (0 2 4)(1 3)。在这里,括号中的每组术语表示“向前循环循环这些元素”。这意味着循环 0 到 2 所在的位置, 2 到 4 所在的位置, 4 到 0 所在的位置,然后循环 1 到 3 所在的位置, 3 到 1 所在的位置。

如果您对特定数组进行了循环分解,则只需将所有内容向后循环一个位置,就可以按排序顺序将其取回,从而使写入次数最少。循环排序背后的想法是尝试确定输入数组的循环分解是什么,然后将其反转以将所有内容放回原处。

这个挑战的一部分是弄清楚一切最初属于哪里,因为循环分解假设你知道这一点。通常,循环排序的工作原理是遍历每个元素并计算有多少元素小于它。这很昂贵——它有助于排序算法的 Θ(n 2 ) 运行时间——但不需要任何写入。

于 2015-08-21T19:07:38.427 回答
0

如果有人需要,这是一个 python 实现

def cycleSort(vector):
    writes = 0

    # Loop through the vector to find cycles to rotate.
    for cycleStart, item in enumerate(vector):

        # Find where to put the item.
        pos = cycleStart
        for item2 in vector[cycleStart + 1:]:
            if item2 < item:
                pos += 1

        # If the item is already there, this is not a cycle.
        if pos == cycleStart:
            continue

        # Otherwise, put the item there or right after any duplicates.
        while item == vector[pos]:
            pos += 1
        vector[pos], item = item, vector[pos]
        writes += 1

        # Rotate the rest of the cycle.
        while pos != cycleStart:

            # Find where to put the item.
            pos = cycleStart
            for item2 in vector[cycleStart + 1:]:
                if item2 < item:
                    pos += 1

            # Put the item there or right after any duplicates.
            while item == vector[pos]:
                pos += 1
            vector[pos], item = item, vector[pos]
            writes += 1

    return writes


x = [0, 1, 2, 2, 2, 2, 1, 9, 3.5, 5, 8, 4, 7, 0, 6]
w = cycleSort(x) 
print w, x
于 2016-04-09T18:52:19.597 回答