【问题标题】:Why do I get a random number in the first element of the sorted array?为什么我在排序数组的第一个元素中得到一个随机数?
【发布时间】:2020-12-07 18:18:00
【问题描述】:

我是 C 的新手,当我这样做时,会排列列表中的元素:

#include <stdlib.h>
#include <stdio.h>

int main()
{
    int list[] = {6, 4, 8, 1, 0, 9, 11, 50, 60, 10};
    int i, j, aux, k;
    int len = sizeof(list) / sizeof(list[0]);
    for (i = 0; i < len; i++)
    {
        for (j = 0; j < len; j++)
        {
            if (list[j] > list[j + 1])
            {
                aux = list[j + 1];
                list[j + 1] = list[j];
                list[j] = aux;
            }
        }
    }
    for (k = 0; k < len; k++)
    {
        printf("%d  ", list[k]);
    }
    return 0;
}

输出:

-13168  0  1  4  6  8  9  10  11  50

为什么第一个值是-13168

【问题讨论】:

  • 您在访问数组之外​​进行排序,所以奇怪的值是您从数组外部读取的内容。
  • 我是如何访问数组之外​​的,我从 0 开始到数组长度
  • 是的,然后你从前面读到。
  • if (list[j] &gt; list[j+])aux = list[j+1]; 等 — 当 jlen - 1j + 1lenlist[len] 时,这些在数组外读取。
  • list[j + 1] 不存在时j == n - 1

标签: arrays c sorting bubble-sort


【解决方案1】:

正如list[j + 1] 所说,超出了数组的范围,正如所说,使用for (j = 0; j &lt; len - 1; j++) 将解决这个问题。

然而,事实上,第二个循环将始终遍历整个数组,这不是必需的,因为值被交换 i 将增加并且需要的迭代次数将变得更少,因此您可以使用i 迭代器在第二个循环的停止条件下,从而通过减少迭代次数来优化它。

for (i = 0; i < len - 1; i++) //len - 1 is enough
{
    for (j = 0; j < len - i - 1; j++) //replacing < len with  < len - i - 1
    {
        if (list[j] > list[j + 1])
        {
            aux = list[j + 1];
            list[j + 1] = list[j];
            list[j] = aux;
        }
    }
}

Live demo

这是一种更合适的冒泡排序。

即使是这么小的阵列,性能差异也很明显,但仍有改进的余地。

当循环中不再发生交换时,这意味着数组已排序,因此如果我们要添加一个标志以在发生这种情况时停止排序,那么您将拥有一个非常优化的冒泡排序算法:

int ordered = 0;
//...    
for (i = 0; i < len - 1; i++)
{
    ordered = 0; //reset flag
    for (j = 0; j < len - i - 1; j++)
    {
        if (list[j] > list[j + 1])
        {
            aux = list[j + 1];
            list[j + 1] = list[j];
            list[j] = aux;  
            ordered = 1; //if the swap occurs, the ordering continues
        }
    }
    if (ordered == 0) //otherwise the array is ordered and the ordering ends
        break; 
}

Live demo

从测试中可以看出,这是一种非常快速的冒泡排序。

Benchmark results:

【讨论】:

    【解决方案2】:

    第二个循环有错误:

    for(j = 0; j < len; j++) 
    

    应该是

    for(j = 0; j < len - 1; j++)
    

    【讨论】:

      【解决方案3】:

      当您访问list[j+1] 时,您在最后一次迭代中超出了界限。

      所以,将inner loop 更改为:

             for(j=0;j<len-1;j++){ }
      

      【讨论】:

        【解决方案4】:

        你的外循环没用。你从不使用i。我想你想要:

        for(i=0;i<len;i++){
            for(j=0;j<i;j++){
                if(list[j] > list[i]){
                    aux = list[i];
                    list[i] = list[j];
                    list[j] = aux;
                }
            }
        }
        

        【讨论】:

        • 排序需要经常执行内部循环以完成所有需要的冒泡......
        • 外循环并非没用——尽管它可能效率低下。
        【解决方案5】:

        您的ij 都会遍历数组中所有合法索引的范围。
        但是您确实可以访问数组之外​​的list[j+1],在那里读取并对从那里获得的值进行排序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-08
          • 1970-01-01
          • 2022-01-13
          • 1970-01-01
          • 1970-01-01
          • 2013-06-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多