我在quora中遇到了一个排序代码,我对某些代码行感到非常困惑,如果有人向我解释它,那将是一个很大的帮助。
代码如下:
#include <stdio.h>
int array[1000001] = {0};
int main(){
int i,j;
scanf("%d",&j);
int x;
for (i=0;i<j;i++){
scanf("%d",&x);
array[x]++;
}
for (i=0;i<1000001;i++){
while(array[i]>0){
printf("%dn",i);
array[i]--;
}
}
return 0;
}
有人可以解释
for(i=0;i<j;i++)
{
scanf("%d",&x);
array[x]++;
}
在这里
for (i=0;i<1000001;i++)
{
while(array[i]>0)
{
printf("%dn",i);
array[i]--;
}
}
dn
代表什么?
答案 0 :(得分:1)
到目前为止,这是不从法定人数或其他来源复制任何内容而又不了解其行为的最佳理由。
无论如何,它不能确保任何输入是否正确。
for(i=0;i<j;i++)
{
scanf("%d",&x);
// Are you sure that 'x' is always a valid int value and is less than your array size?
// No, if a monkey enters 200000 here, kabooom!
array[x]++;
}
在此for
循环中,该循环将重复j
次,输入类型为int
的输入,并且该索引处的值将递增,以知道输入了什么值通过将该索引标记为1
。
for (i=0;i<1000001;i++)
{
while(array[i] > 0)
{
printf("%dn",i);
array[i]--;
}
}
这在设计上很糟糕,因为如果我仅输入3个数字进行排序,它仍然会迭代1000001次。 但是,它适用于预期/故意限制的输入值。
例如,假设用户输入了6个值:4
,2
,7
,0
,6
,8
因此,j = 6
和array
的内容将为全零,除了第4、2、7、0、6和8个索引。
现在,此while
循环可以完成工作:它检查是否设置了第i
个索引,即该索引是否由用户未输入。因此,while
循环内的代码将仅对第4、2、7、0、6和8个索引执行。
为了说明该值的打印方式,让我们先运行一下代码,最初的i
是0
。
// Is ith index 1?
while (array[i] > 0) // i is 0
{
// Yes it is,
printf("%d ", i);
// See above, Prints 0 - not 1!
// Printing 'i' is the trick, instead of printing array[i]..
array[i]--; // Note, makes it zero!
}
对于下一次迭代,i
是1
// Is ith index 1? - No, so move on to next index
while (array[i] > 0) // i is 1
{
//
}
让我们说迭代达到了第7个索引,
// Is ith index 1?
while (array[i] > 0) // i is 7
{
// Yes it is,
printf("%d ", i);
// See above, Printing 'i' is the trick,
// instead of printing array[i]..
array[i]--; // Note, makes it zero!
}
毫无疑问,这将对数字进行排序,但是带有一些预定义的内容。 此外,您可以/应该添加一些实现以根据是否需要执行排序来获取数组中的排序值。
最后,"%dn"
不是格式说明符。它可能是"%d\n"
。
如果按原样保持不变,它将在打印的每个数字之后附加n
作为字符,毫无意义。
答案 1 :(得分:0)
这会尝试读取一些数字,并冒昧地指出读取可能会失败。
scanf("%d",&j);
因此,j
因此可能未初始化。
这将形成一个循环,该循环将执行j
个步骤,即可能是未初始化的循环数。
for(i=0;i<j;i++)
这会尝试在每个循环中读取一次数字,而不关心潜在的故障。
scanf("%d",&x);
然后,它使用可能未初始化或未更新的数字x
访问数组。
array[x]++;
如果x
由于任何原因不一致,则访问可能超出数组,这会引入潜在的不确定行为。
但是,如果成功,则数组条目将增加一个。
大部分数组条目都是通过这种方式隐式初始化的,而不是因为{0}
。
因此,索引处与读取编号匹配的数组项将被累加。
总计,对希望正确格式化的输入中每个数字的出现次数进行计数。
没有排序。
这会循环遍历数组中的所有条目,从较低的索引开始,即从输入中出现的值的较低值开始。
for (i=0;i<1000001;i++)
如果数组中的条目不为0,则打印索引/值,并减少计数直到条目为零。
{
printf("%dn",i);
array[i]--;
}
即当前索引/值的打印频率与在输入中看到的频率相同。
隐式地,不会打印输入中未出现的任何值。
有关“%dn”的信息,请看这里:
Is %dn a format string?
为什么输出中不会出现“ n”,而输出中确实包含无法解释的换行符,这是最合理的解释,是在代码中,“ n”实际上是一个“ \ n”,产生了显示的输出,但是在发布时却丢失了代码。
(我同意@WedaPashi的观点,该代码将在输入其他所有漏洞之外的输入时出现负数麻烦。)
我认为,低值解决方案的表观速度会因循环许多高值空条目而受到破坏。它提供了令人误解的快速输出,同时花了很长时间不进行任何操作才能真正完成数组的操作。