这些功能如何运作?

时间:2014-12-16 23:03:35

标签: c arrays algorithm radix-sort

您能解释一下以下两种算法的工作原理吗?

int countSort(int arr[], int n, int exp)
{
    int output[n]; 
    int i, count[n] ;
    for (int i=0; i < n; i++)
       count[i] = 0;
    for (i = 0; i < n; i++)
        count[ (arr[i]/exp)%n ]++;
    for (i = 1; i < n; i++)
        count[i] += count[i - 1];
    for (i = n - 1; i >= 0; i--)
    {
        output[count[ (arr[i]/exp)%n] - 1] = arr[i];
        count[(arr[i]/exp)%n]--;
    }
    for (i = 0; i < n; i++)
        arr[i] = output[i];
}


void sort(int arr[], int n)
{
    countSort(arr, n, 1);
    countSort(arr, n, n);
}

我想在这个数组中应用算法:

enter image description here

在调用函数countSort(arr,n,1)之后,我们得到了这个:

enter image description here

当我调用函数countSort(arr,n,n)时,在此for循环中:

for (i = n - 1; i >= 0; i--)
{
    output[count[ (arr[i]/exp)%n] - 1] = arr[i];
    count[(arr[i]/exp)%n]--;
}

我得到输出[-1] = arr [4]。

但阵列没有这样的位置......

我做错了吗?

编辑:考虑到数组arr [] = {10,6,8,2,3},数组计数将包含以下元素:

enter image description here

这些数字代表什么?我们如何使用它们?

2 个答案:

答案 0 :(得分:2)

计算排序非常简单 - 让我们假设您有一个包含范围1..3中数字的数组:
[3,1,2,3,1,1,3,1,2]

您可以计算数组中每个数字出现的次数:
count[1] = 4
count[2] = 2
count[3] = 3

现在您知道在排序数组中,
号码1将占据0..3个位置(从0count[1] - 1),然后是 位置2上的号码4..5(从count[1]count[1] + count[2] - 1),然后是 位置3上的号码6..8(从count[1] + count[2]count[1] + count[2] + count[3] - 1)。

现在您知道每个数字的最终位置,您只需将每个数字插入正确的位置即可。这基本上是countSort函数的作用。

但是,在现实生活中,您的输入数组不会只包含范围1..3中的数字,因此解决方案是首先对最低有效位(LSD)上的数字进行排序,然后对LSD-1 ...进行排序。最重要的数字 这样,您可以通过对范围0..9中的数字进行排序(十进制数字系统中的单个数字范围)来对较大的数字进行排序 此代码:(arr[i]/exp)%n中的countSort仅用于获取这些数字。 n是数字系统的基础,因此对于十进制,您应使用n = 10exp应以1开头,并在每次迭代中乘以基数以获得连续数字。
例如,如果我们想从右侧获得第三位数字,我们会使用n = 10exp = 10^2
x = 1234(x/exp)%n = 2

此算法称为基数排序,在维基百科上详细解释:http://en.wikipedia.org/wiki/Radix_sort

答案 1 :(得分:1)

花了一些时间来挑选你的countSort例程并试图确定你正在做什么与普通的radix排序相比。有些版本会分割迭代和实际的排序例程,这似乎是您尝试使用countSortsort函数的方法。然而,经过这次练习后,很明显你错过了包括排序例程的必要部分。在修复原始代码中的各种编译/声明问题后,以下内容会添加您忽略的部分。

countSort函数中,count数组的大小错误。它必须是base的大小,在本例中为10。 (您有5)您在整个函数中混淆了expbase的使用。 exp变量逐步通过10的幂,允许您在与modulo base操作结合时获取数组中每个元素的值和位置。你改为modulo n了。这个问题也渗透到你的循环范围中,你有许多循环索引迭代0 < n,其中正确的范围是0 < base

您错过了在原始数组中找到最大值,然后用于限制通过数组的次数来执行排序。实际上,countSort中的所有现有循环都必须属于外循环迭代while (m / exp > 0)。最后,您在外部循环中省略了将exp增量应用于对数组中的每个元素应用排序所必需的。我猜你刚才感到困惑,但我赞扬你努力重写排序例程而不仅仅是从其他地方复制/粘贴。 (您可能已复制/粘贴,但如果是这样的话,则还有其他问题......)

随着每个问题的解决,排序工作。看看变化并了解它在做什么。 radix sort/count sortdistribution sorts依赖于数字出现的位置和操纵索引而不是将值相互比较,这使得这种类型的排序首先难以理解。如果您有任何疑问,请告诉我。我尝试在整个函数中保留您的命名约定,添加了一对被省略的并且防止以10为基础进行硬编码。

#include <stdio.h>

void prnarray (int *a, int sz);

void countSort (int arr[], int n, int base)
{
    int exp = 1;
    int m = arr[0];
    int output[n]; 
    int count[base];
    int i;

    for (i = 1; i < n; i++)                 /* find the maximum value           */
        m = (arr[i] > m) ? arr[i] : m;

    while (m / exp > 0)
    {
        for (i = 0; i < base; i++)
            count[i] = 0;                   /* zero bucket array (count)        */

        for (i = 0; i < n; i++)
            count[ (arr[i]/exp) % base ]++; /* count keys to go in each bucket  */  

        for (i = 1; i < base; i++)          /* indexes after end of each bucket */
            count[i] += count[i - 1];

        for (i = n - 1; i >= 0; i--)        /* map bucket indexes to keys       */
        {
            output[count[ (arr[i]/exp) % base] - 1] = arr[i];
            count[(arr[i]/exp)%n]--;
        }

        for (i = 0; i < n; i++)             /* fill array with sorted output    */
            arr[i] = output[i];

        exp *= base;                        /* inc exp for next group of keys   */
    }    
}

int main (void) {

    int arr[] = { 10, 6, 8, 2, 3 };
    int n = 5;
    int base = 10;

    printf ("\n The original array is:\n\n");
    prnarray (arr, n);

    countSort (arr, n, base);

    printf ("\n The sorted array is\n\n");
    prnarray (arr, n);

    printf ("\n");

    return 0;
}

void prnarray (int *a, int sz)
{
    register int i;
    printf ("  [");
    for (i = 0; i < sz; i++)
        printf (" %d", a[i]);
    printf (" ]\n");
}

<强>输出:

$ ./bin/sort_count

 The original array is:

  [ 10 6 8 2 3 ]

 The sorted array is

  [ 2 3 6 8 10 ]