n个数字的排序(C语言)

题目:

        输入n个数字,升/降序排列输出(以升序为例)

输入示例:8 2 5 6 3

输出示例:2 3 5 6 8

本题目是上一篇文章(《求n个数的最大数(C语言)》)的进阶:求n个数的最大数(C语言)

思路:冒泡排序

        本质是将上一篇文章(《求n个数的最大数(C语言)》)的思路作为一个循环单位循环进行

 详细思路:

第一次循环

  1. 将第1个数字与第2个数字比较,若大于,二者数值交换,否则不变
  2. 将第2个数字与第3个数字比较,若大于,二者数值交换,否则不变
  3. ...
  4. 将第n-1个数字与第n个数字比较,若大于,二者数值交换,否则不变

第二次循环

  1. 将第1个数字与第2个数字比较,若大于,二者数值交换,否则不变
  2. 将第2个数字与第3个数字比较,若大于,二者数值交换,否则不变
  3. ...
  4. 将第n-2个数字与第n-1个数字比较,若大于,二者数值交换,否则不变

...

第n-1次循环

  1. 将第1个数字与第2个数字比较,若大于,二者数值交换,否则不变

排序结束   输出


难点一:冒泡排序的实现

错误示例:

    for (i=1;i<n;i++)
		{
			if (a[i]<a[i-1])
			t=a[i];
			a[i]=a[i-1];
			a[i-1]=t;
		}

正确示例:

 for(i = 0; i < n - 1; i++)
    {
        for(j = 0; j < n - i - 1; j++)
        {
            if(a[j] > a[j + 1])
            {
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }
        }
    }

二者区别:前者只进行了一次遍历,相当于只做了思路中的第一个循环(这样的效果仅仅是把最大的元素调换到最后一个位置),而后者便是双层循环,将思路中的所有内容完全贯彻执行了

难点二:一维数组的输出

错误示例:

    printf("the ranged elements are :%d",a[i]);

正确示例:

    printf("the sorted elements are: ");
    for(i = 0; i < n; i++)
    {
        printf("%d ", a[i]);
    }
  1. 后者 语法规范,使用循环输出
  2. 后者的英语表达更合适(sorted)

难点三:for循环中的第二个条件:变量范围的把握    [引用部分代码是完整代码(底部提供)中的内循环部分]

错误示范:

for(j = 0; j < n - i ; j++)

正确示范:

for(j = 0; j < n - i - 1; j++)

1. 条件 j < n - i

  • 循环次数:内层循环会执行 n - i 次(从 j=0 到 j=n-i-1)。
  • 适用场景
    • 当算法需要遍历当前未处理的全部元素时(例如:每轮处理的范围不收缩,或需要覆盖所有剩余元素)。
    • 可能用于需要重复访问所有元素的逻辑(如某些动态规划或未优化的简单算法)。
  • 风险
    • 如果循环内部涉及对 j+1 的引用(例如比较相邻元素),可能会导致数组越界(访问 arr[j+1] 时 j 最大为 n-i-1,而 j+1 可能达到 n-i,超出数组范围)。

2. 条件 j < n - i - 1

  • 循环次数:内层循环会执行 n - i - 1 次(从 j=0 到 j=n-i-2)。
  • 适用场景
    • 当算法需要避免访问越界元素时(例如:比较 arr[j] 和 arr[j+1])。
    • 冒泡排序的经典实现:每轮外层循环 i 会将一个最大元素“冒泡”到末尾,因此内层循环无需再处理已排序的部分。
    • 适用于需要严格边界控制的场景。

混淆一:数组越界

错误示例:

 for(i = 0; i <= n -1; i++)               //错误在这一行   //有的人也错写为i<n
    {
        for(j = 0; j < n - i - 1; j++)
        {
            if(a[j] > a[j + 1])
            {
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }
        }
    }

正确示例:(同难点一)

 for(i = 0; i < n - 1; i++)
    {
        for(j = 0; j < n - i - 1; j++)
        {
            if(a[j] > a[j + 1])
            {
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }
        }
    }

 错误:数组越界(详见《求n个数的最大数(C语言)》难点三)(链接在顶部)

混淆二:升序排序和降序排序的区别

升序:

    if(a[j] > a[j + 1]) 
            {  
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }

降序:

        if(a[j] < a[j + 1])
            {
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }

总结

完整代码:

#include <stdio.h>

int main() 
    {
    int n, i, j, t;
    printf("please input the number of the elements: ");
    scanf("%d", &n);
    
    // 动态分配内存
    int a[n];
    
    printf("please input the elements: ");
    for(i = 0; i < n; i++) 
    {
        scanf("%d", &a[i]);
    }

    // 使用冒泡排序对数组进行排序
    for(i = 0; i < n - 1; i++)
     {
        for(j = 0; j < n - i - 1; j++) 
          {
            if(a[j] > a[j + 1])
             {  // 这里是升序排序,如果需要降序排序,改为 a[j] < a[j + 1]
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }
        }
    }

    printf("the sorted elements are: ");
    for(i = 0; i < n; i++) 
    {
        printf("%d ", a[i]);
    }
    printf("\n");

    return 0;
}

输出效果:


补充

使用scanf别忘加&
把所有要定义的变量统一定义在前面的优缺点:

        优点

  1. 清晰性:所有变量在函数开头定义,可以一目了然地看到所有变量。

  2. 兼容性:与旧的 C 标准兼容。

        缺点

  1. 可读性:变量定义与使用相距较远,可能会降低代码的可读性。

  2. 作用域:变量的作用域更大,可能会导致意外的错误。

        现代实践

      现代 C 编程更倾向于在需要时就近定义变量,这样可以提高代码的可读性和维护性。

像这样结果是连着输出数字的 ,在printf后边最好加个空格或者\n
使用VS code改的次数多了即使写对结果也输出不合格,可以试试把所属任务文件夹中的项目全删了重新复制粘贴上去再编译运行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pniubi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值