📜  珠子排序|一种自然排序算法

📅  最后修改于: 2021-04-24 20:12:28             🧑  作者: Mango

此算法也称为重力排序,它是从自然现象中汲取灵感的,设计时要牢记物体(或珠子)在重力作用下掉落。

想法:正数由一组像算盘上的珠子表示。

牛血清白蛋白

使用Bead Sort对{7,2,1,4,4,2}进行排序。如果下方有空间,珠子将一一掉落。

  1. 就像上面的图像一样,小珠从上到下表示以下数字:7,2,1,4,2。现在,假设这是时间t = 0时小珠的位置,每经过一秒,小珠就会如果它们下面没有珠子,则跌落一级。在这种情况下,它们只是停留在它们下面的珠子上。(杆从左到右编号,水平从下到下编号为1、2,…………n。)
  2. 现在,在时间t = 1时,从左起的前两个杆中的底部2个珠子停留在它们的位置,而从第二个杆的顶部开始的第二个珠子下降一个高度,停在其下面的珠子上。在第2级的第3和第4杆中的珠子下降到第1级。同时,在第3至7杆中的珠子下降了一级。现在,从上到下的数字变为:2、6、2、2、4。
  3. 这一直持续到时间t = 4 ,在这里我们得到了从上到下的数字排序序列,即:1、2、2、4、7。

为什么这样称呼呢?

当人们尝试可视化此算法时,似乎珠子在重力的影响下掉落到最底层,它们可以到达,导致这组珠子从下到上以降序排列。如果您无法形象地查看此链接,请访问此链接

假设我们必须对数字3、4、1、2进行排序。以上算法将像这样工作。

珠子排序工作

下面是代码,请在查看代码之前尝试自己实施。

编码:

// C++ program to implement gravity/bead sort
#include 
using namespace std;
  
#define BEAD(i, j) beads[i * max + j]
  
// function to perform the above algorithm
void beadSort(int *a, int len)
{
    // Find the maximum element
    int max = a[0];
    for (int i = 1; i < len; i++)
        if (a[i] > max)
           max = a[i];
  
    // allocating memory
    unsigned char beads[max*len];
    memset(beads, 0, sizeof(beads));
  
    // mark the beads
    for (int i = 0; i < len; i++)
        for (int j = 0; j < a[i]; j++)
            BEAD(i, j) = 1;
  
    for (int j = 0; j < max; j++)
    {
        // count how many beads are on each post
        int sum = 0;
        for (int i=0; i < len; i++)
        {
            sum += BEAD(i, j);
            BEAD(i, j) = 0;
        }
  
        // Move beads down
        for (int i = len - sum; i < len; i++)
            BEAD(i, j) = 1;
    }
  
    // Put sorted values in array using beads
    for (int i = 0; i < len; i++)
    {
        int j;
        for (j = 0; j < max && BEAD(i, j); j++);
  
        a[i] = j;
    }
}
  
// driver function to test the algorithm
int main()
{
    int a[] = {5, 3, 1, 7, 4, 1, 1, 20};
    int len = sizeof(a)/sizeof(a[0]);
  
    beadSort(a, len);
  
    for (int i = 0; i < len; i++)
        printf("%d ", a[i]);
  
    return 0;
}

输出:

1 1 1 3 4 5 7 20

时间复杂度:
该算法的运行时复杂度范围从O(1)到O(S)(S是输入整数的总和),具体取决于用户的角度。最后,提出了三种可能的实现方式。

  1. O(1) :将所有珠子作为一个(同时)操作放在一起。这种复杂性无法在实践中实现。
  2. O( n^1^/^2 ):在使用重力的真实物理模型中,让珠子掉落所需的时间与最大高度的平方根成正比,最大平方根与n成正比。
  3. O(n) :由于不同的行数等于n,因此将帧中的一排珠子(代表一个数字)丢弃是一种独特的操作。
  4. O(S) :将每个珠子作为单独的操作放下,因为S是所有珠子的总和。

像鸽子洞排序一样,珠排序也很不寻常,因为在最坏的情况下它的执行速度可能比O( n log n ),在最坏的情况下进行比较排序时可能会获得最快的性能。这是可能的,因为珠子排序的键始终是正整数,并且珠子排序会利用其结构。

空间复杂性:珠子分类是废物的记录保持者。额外内存的成本超过了存储阵列本身的成本。其内存复杂度为O( n^2 )

参考:

  • https://www.wikiwand.com/cn/Bead_sort
  • https://kukuruku.co/post/bead-sort/
  • https://rosettacode.org/wiki/排序算法/ Bead_sort
  • https://www.cs.auckland.ac.nz/~mjd/misc/BeadSort5.pdf