如何在线性时间内对int数组进行排序?

时间:2014-02-25 15:37:09

标签: c arrays sorting

我已经做了一个功课来做一个按升序排序数组的程序。我这样做了:

#include <stdio.h>
int main()
 {
    int a[100],i,n,j,temp;
    printf("Enter the number of elements: ");
    scanf("%d",&n);
    for(i=0;i<n;++i)
      {
       printf("%d. Enter element: ",i+1);
       scanf("%d",&a[i]);
     }
    for(j=0;j<n;++j)
    for(i=j+1;i<n;++i)
     {
         if(a[j]>a[i])
          {
             temp=a[j];
             a[j]=a[i];
             a[i]=temp;
         }
    }
    printf("Ascending order: ");
    for(i=0;i<n;++i)
        printf("%d  ",a[i]);
    return 0;
}

输入不会超过10个数字。这可以用比我在这里做的少量代码完成吗?我希望代码尽可能地最短。任何帮助都将受到赞赏。谢谢!

2 个答案:

答案 0 :(得分:4)

你有10行进行排序。 如果你被允许使用别人的工作(后续注释表明你不能这样做),你可以通过编写比较器函数并调用标准C库qsort()来减少这种情况。功能:

static int compare_int(void const *v1, void const *v2)
{
    int i1 = *(int *)v1;
    int i2 = *(int *)v2;
    if (i1 < i2)
        return -1;
    else if (i1 > i2)
        return +1;
    else
        return 0;
}

然后电话是:

qsort(a, n, sizeof(a[0]), compare_int);

现在,我按照我做的方式写了这个函数。特别是,它避免了算术溢出,写这不是:

static int compare_int(void const *v1, void const *v2)
{
    return *(int *)v1 - *(int *)v2;
}

此外,原始模式概括为比较结构等。您比较第一个字段的不等式返回适当的结果;如果第一个字段不相等,那么你比较第二个字段;然后是第三个,然后是N th ,只有在每个比较显示值相等时才返回0。

显然,如果您应该编写排序算法,那么除了调用qsort()之外,您还需要做更多的工作。您的算法是冒泡排序。它是最低效的分选技术之一 - 它是O(N 2 )。你可以查找插入排序(也是O(N 2 ))但比冒泡排序更有效,或者选择排序(也是二次),或者Shell排序(非常大致为O(N 3) / 2 )),或堆排序(O(NlgN)),或快速排序(平均为O(NlgN),但在最坏的情况下为O(N 2 ),或简介排序。唯一可能比你写的更短的是插入和选择排序;对于大量数据,其他的将更长但更快。对于像10或100这样的小集合,效率并不重要 - 所有种类都可以。但是当你进入1,000或1,000,000个条目时,排序算法确实很重要。关于不同的排序算法,您可以在Stack Overflow上找到很多问题。您可以在维基百科中轻松找到所提及的任何和所有算法的信息。

顺便提一下,如果输入的数量不超过10个,则不需要大小为100的数组。

答案 1 :(得分:2)

如果你知道数组元素的范围,一种方法是使用另一个数组来存储每个数组元素的频率(所有元素应该是int :))并打印排序的数组。我发布了大量元素(10 6 )。您可以根据需要减少它:

#include <stdio.h>
#include <malloc.h>
int main()
{
    int t, num, *freq = malloc(sizeof(int)*1000001);
        for(int i = 0; i < 1000001; i++)
            freq[i] = 0;
    scanf("%d",&t);

    for(int i = 0; i < t; i++)
    {
        scanf("%d", &num);
        freq[num]++;
    }
    for(int i = 0; i < 1000001; i++)
        if(freq[i])
            while(freq[i]--)
                printf("%d\n", i);
}  

可以进一步修改此算法。修改后的版本称为计数排序,它会在 Θ(n) 时间内对数组进行排序。

Counting sort 1

  

计数排序假定每个n输入元素都是该范围内的整数   0 to k,对于某个整数k。当 k = O(n)时,排序会在 Θ(n) 时间内运行。   对于每个输入元素x,计数排序确定较少的元素数   比x。它使用此信息将元素x直接放入其中的位置   输出数组。例如,如果17个元素小于x,则x属于输出   我们必须稍微修改这个方案以处理其中的情况   几个元素具有相同的值,因为我们不想将它们全部放入   同样的立场。

     

在计算排序的代码中,我们假设输入是一个数组A[1...n]和   因此 A.length = n 。我们需要另外两个数组:数组B[1....n]包含数组   排序输出,数组C[0....k]提供临时工作存储。

这个算法的伪代码:

for i ← 1 to k do
c[i] ← 0
for j ← 1 to n do
    c[A[j]] ← c[A[j]] + 1
//c[i] now contains the number of elements equal to i
for i ← 2 to k do
    c[i] ← c[i] + c[i-1]
// c[i] now contains the number of elements ≤ i
for j ← n downto 1 do
    B[c[A[i]]] ← A[j]
    c[A[i]] ← c[A[j]] - 1  

<子> 1。内容取自Introduction to Algorithms Thomas H. Cormen等人。