以下代码如何打印排序数组?我无法理解这背后的逻辑。
#include <stdio.h>
int a[1000000];
int main(void) {
int t, i = 0, temp;
scanf("%d", &t);
for (i = 0; i < t; i++) {
scanf("%d", &temp);
a[temp]++;
}
for (i = 0; i <= 1000000; i++) {
while (a[i] != 0) {
printf("%d\n", i);
a[i]--;
}
}
return 0;
}
答案 0 :(得分:1)
让我们分成更小的部分:
scanf("%d", &t);
这很简单:它向用户询问一个整数,并将其存储在t
中。此变量表示我们要排序的整数数。
for(i = 0; i < t ; i++)
{
scanf("%d", &temp);
a[temp]++;
}
这段代码要求用户输入t
个整数。在每次迭代中,数组temp
的位置a
的值都会增加。
这是什么意思?将数组a
视为计数器数组,其中每个计数器最初设置为0.当用户输入新的整数n
时,n
的计数器(即{{1} })增加。
在循环结束时,数组a[n]
的第j
个元素存储数字a
的出现次数。
假设您有以下数字要排序:
j
在第一次迭代之前:4 1 8 7 6 7
a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
a[4]++ => a = [0, 0, 0, 0, 1, 0, 0, 0, 0, ...]
a[1]++ => a = [0, 1, 0, 0, 1, 0, 0, 0, 0, ...]
a[8]++ => a = [0, 1, 0, 0, 1, 0, 0, 0, 1, ...]
a[7]++ => a = [0, 1, 0, 0, 1, 0, 0, 1, 1, ...]
a[6]++ => a = [0, 1, 0, 0, 1, 0, 1, 1, 1, ...]
此时,您已经完成了打印它们所需的一切:
a[7]++ => a = [0, 1, 0, 0, 1, 0, 1, 2, 1, ...]
第二个for(i=0; i <= 1000000; i++)
{
while(a[i] != 0)
{
printf("%d\n", i);
a[i]--;
}
}
循环遍历for
的所有元素,即所有&#39;计数器&#39;。当计数器大于0时,打印a
的次数等于计数器的值。回想一下,i
不仅是此循环中数组当前元素的位置,而且它也是与计数器关联的数字。
这是一个聪明的算法,不需要比较,但它有一些陷阱。
可以修改算法的实现以解决或缓解上述问题。
如果您想了解有关此主题的更多信息,请参阅Counting Sort
答案 1 :(得分:1)
首先,数组应该是[1000001],或者for循环应该是for(i=0;i<1000000;i++)
。假设第二个答案
据我所知,数组中允许的最大数量必须为999999。 该程序的主要逻辑(实现Count Sort)是:
<小时/>
int a[1000000];
:这声明一个数组,用于保存每个数字的频率,范围为0 - 999999,每个数字的频率与数字本身的索引相同,即数字n的频率将为[n]。< p>
for(i=0;i<t;i++)
{
scanf("%d",&temp);
a[temp]++;
}
此代码扫描每个元素并更新其频率(每次出现时增加1)。
for(i=0;i<=1000000;i++)
{
while(a[i]!=0)
{
printf("%d\n",i);
a[i]--;
}
}
遍历每个元素0到999999,并为每个元素: 打印元素并将其频率降低1,直到其频率变为0,即打印元素与其频率相同的次数。
<小时/> 为什么会这样?
我们得到一个数组,按升序排序(从代码中假设)。 升序意味着首先是较小的数字。
因此,我们从范围内的最小数量开始,并检查它是否存在。如果它存在于数组中,我们将它打印出它在数组中出现的次数。一旦完成最小数字,我们将继续下一个最小数字并重复相同的数字。
重复相同的直到999999将确保打印的数组现在按升序排列,因为我们首先打印数字较小的数组,并且与原始数组相同,因此,没有数字会出现比原始数组更多或更少的数字
答案 2 :(得分:0)
步骤很简单:
a
用于计算输入的每个数字的出现次数。 这种非常简单的排序方法称为计数排序。
请注意,该程序有缺点和潜在的错误:
未测试scanf()
的返回值,如果输入无法转换为整数,则会导致潜在的未定义行为。
数字必须在0
到999999
的范围内。超出此范围的数字将导致未定义的行为。
最终循环包含迭代到1000000
,访问超出最后一个元素的数组,导致未定义的行为。
以下是更正后的版本:
#include <stdio.h>
int a[1000000];
int main(void) {
int t, i, temp;
if (scanf("%d", &t) != 1)
return 1;
for (i = 0; i < t; i++) {
if (scanf("%d", &temp) != 1)
return 1;
if (temp < 0 || temp >= 1000000) {
fprintf(stderr, "number is out of range: %d\n", temp);
continue;
}
a[temp]++;
}
for (i = 0; i < 1000000; i++) {
while (a[i] != 0) {
printf("%d\n", i);
a[i]--;
}
}
return 0;
}