替换选择排序

Replacement selection sorting

所以我一直在尝试实现这个算法,但我不太确定从哪里开始。基本上根据我的理解,您可以通过两种方式实现它,通过将顶层排序为最小(minHeap)或顶层是所有事物的最大值(maxHeap)。我在谷歌上搜索了很多关于这两种方式的任何一种,但我无法掌握如何实际实施它。我一般不明白我会说的想法,任何人都可以解释一下这是如何工作的吗?比如 minHeap 应该如何工作,或者 maxHeap 应该如何工作。 提前致谢!

我假设您对数组中的二叉堆实现有基本的了解。

假设您有一个整数数组,您希望对其进行升序排序。一种方法是重新排列数组中的项目,使它们形成最大堆。

然后,将顶部项(数组中最大的项)与堆中的最后一项交换,将堆计数减 1,然后从上到下将项筛选到堆中的新位置.最后,数组中的第一项将是下一个最大的项。您对每个项目重复该操作,并且您的数组已排序。

举个小例子。给定数组 [4,7,6,1,3,5,2],您使用 Floyd 算法将它们重新排列成一个堆。

for (int i = array.length/2; i >= 0; i--)
{
    siftDown(i);
}

这是一个 O(n) 操作。

完成后,数组将排列在二进制堆中。在这种情况下,堆将是 [7,4,6,1,3,5,2],或者:

       7
     4   6
    1 3 5 2

因此,我们将根项与最后一项交换,得到:[2,4,6,1,3,5,7]。我们减少计数并将 2 筛选到适当的位置,给出:[6,4,5,1,3,2,7],或堆表示:

       6
     4   5
    1 3 2

(我省略了 7 因为我们减少了计数。但它仍然在数组的末尾。)

再次,将堆中的顶部项目与最后一个项目交换:[2,4,5,1,3,6,7],减少计数,然后向下筛选:[5,4,2,1,3,6,7]

      5
    4   2
   1 3

如果对堆中剩余的五个项目继续这样做,您将得到一个排序数组。

这个代码非常简单:

int count = array.length-1;
while (count > 0)
{
    swap(array[0], array[count]);
    --count;
    siftDown(0);
}

如果你想做降序排序,你可以用最大堆做上面的操作然后反转数组(O(1) 操作),或者你可以构建一个最小堆开始。

siftDown 方法只是将项目向下移动到适当的位置,遵循二进制堆构造的规则:

void siftDown(int index)
{
    // Left child is at index*2+1. Right child is at index*2+2;
    while (true)
    {
        // first find the largest child
        int largestChild = index*2+1;
        // if left child is larger than count, then done
        if (largestChild >= count)
        {
            break;
        }
        // compare with right child
        if (largestChild+1 < count && array[largestChild] < array[largestChild+1])
        {
            ++largestChild;
        }

        // If item is smaller than the largest child, then swap and continue.
        if (array[index] < array[largestChild])
        {
            swap(array[index], array[largestChild]);
            index = largestChild;
        }
        else
        {
            break;
        }
}