输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。错误写法以及正确写法。

本文探讨了一道经典的数组操作题目:将输入数组的最大值与首个元素交换,最小值与末尾元素交换,并展示了两种实现方式。第一种实现存在特定情况下的Bug,第二种则提供了正确的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。
先看一种解法:

#include<stdio.h>
void swap(int *a, int *b)
{
    int t;
    t = *a;
    *a = *b;
    *b = t;
    return;
}

int main(int argc, char *argv[])
{
    int a[10] = {0};
    int i, min, max;
    min = 0;
    max = 0;
    printf("请输入10个数\n");
    for (i=0; i<=9; i++) 
    scanf("%d", &a[i]);
    for (i=0; i<=9; i++) 
    {
        if (a[min] > a[i])
        min = i;
        if (a[max] < a[i])
        max = i;
    }

   swap(&a[0], &a[max]);
   swap(&a[9], &a[min]);

   for (i=0; i<=9; i++) 
   printf("-->%d", a[i]);
   printf("\n");
}

这种解法乍一看没什么问题,符合题意,但我无意中发现了这种写法的BUG——即如果你输入的10个数, 最小的数刚好在第一位或者最大的数刚好在最后一位的时候,上述代码的处理就会出现错误,按题目的意思,是想让最小的数放在最后一位,最大的数放在第一位。举个例子,假如最小的数在第一位,即a[0];最大的数在第五位,即a[5]。按上述代码处理如下:交换a[5]与a[0],接着交换a[0]与a[9],这样最小的数跑到了第六位的位置,最大的数跑到了最后一位上。显然不符合题目要求。

所以正确的应该是下面的代码:

#include<stdio.h>
void swap(int *a, int *b)
{
    int t;
    t = *a;
    *a = *b;
    *b = t;
    return;
}

int main(int argc, char *argv[])
{
    int a[10] = {0};
    int i, min, max;
    min = 0;
    max = 0;
    printf("请输入10个数\n");
    for (i=0; i<=9; i++) 
    scanf("%d", &a[i]);
    for (i=0; i<=9; i++) 
    {
        if (a[min] > a[i])
        min = i;
        if (a[max] < a[i])
        max = i;
    }
    if (min!=0 && max!=9) 
    {
        swap(&a[0], &a[max]);
        swap(&a[9], &a[min]);
    }
    else if (0==min && 9!=max)
    {
        swap(&a[min], &a[max]);
        swap(&a[9], &a[max]);
    }
    else if (0!=min && 9==max)
    {
        swap(&a[min], &a[max]);
        swap(&a[0], &a[min]);
    }
    else if (0==min && 9==max)
    {
        swap(&a[min], &a[max]);
    }
    for (i=0; i<=9; i++) 
    printf("-->%d", a[i]);
    printf("\n");

}
<think>我们正在讨论C语言实现冒泡排序的正确代码。根据引用内容,我们可以总结出冒泡排序的基本思想:通过多次遍历数组,比较相邻元素,如果顺序不对就交换它们,这样每一趟遍历都会使最大(或最小)的元素“冒泡”到正确的位置。 冒泡排序的步骤: 1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个(这里假设是升序排序)。 2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。这样一趟结束后,最后的元素应该是最大的数。 3. 针对所有的元素重复以上的步骤,除了最后一个(因为每一趟都会将当前最大元素放到正确的位置,所以下一次就可以少比较一个)。 4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 根据引用[1]和引用[2]中的示例代码,我们可以写出一个标准的冒泡排序函数。 注意:引用[1]中的代码是: void bubbleSort(int arr[], int n) { for (int i = 0; i < n-1; i++) { for (int j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { // 交换 int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } 引用[2]中也有类似的代码。 因此,我们可以提供以下代码作为C语言实现冒泡排序的标准写法。 但是,我们还可以考虑一个优化:如果在某一趟遍历中没有发生任何交换,说明数组已经有序,可以提前结束排序。 优化后的冒泡排序代码: void bubbleSort(int arr[], int n) { int swapped; // 标志位,表示是否发生交换 for (int i = 0; i < n-1; i++) { swapped = 0; // 初始化为0 for (int j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { // 交换 int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; swapped = 1; // 发生了交换 } } // 如果这一趟没有发生交换,说明已经有序,提前退出 if (swapped == 0) { break; } } } 下面我们提供一个完整的示例程序,包括主函数来测试冒泡排序。</think>以下是C语言实现冒泡排序的标准代码及其详细说明: ### 冒泡排序算法实现 ```c #include <stdio.h> void bubbleSort(int arr[], int n) { for (int i = 0; i < n-1; i++) { // 外层循环控制遍历轮数 int swapped = 0; // 交换标志位(优化用) for (int j = 0; j < n-i-1; j++) { // 内层循环进行相邻比较 if (arr[j] > arr[j+1]) { // 比较相邻元素 // 交换元素 int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; swapped = 1; // 标记发生交换 } } // 若无交换发生,说明已有序,提前结束 if (swapped == 0) break; } } int main() { int arr[] = {64, 34, 25, 12, 22, 11, 90}; int n = sizeof(arr)/sizeof(arr[0]); printf("排序前数组: "); for (int i=0; i<n; i++) printf("%d ", arr[i]); bubbleSort(arr, n); printf("\n排序后数组: "); for (int i=0; i<n; i++) printf("%d ", arr[i]); return 0; } ``` ### 关键点说明 1. **算法原理**: - 重复遍历数组,比较相邻元素 - 若顺序错误(前>后),则交换它们 - 每轮遍历使最大元素"冒泡"到正确位置[^1] 2. **时间复杂度**: - 最优情况(已排序):$O(n)$(使用swapped标志优化) - 最差情况(逆序):$O(n^2)$ 3. **空间复杂度**: - $O(1)$(原地排序,仅需常量额外空间)[^2] 4. **优化措施**: - `swapped`标志:检测无交换时提前终止 - 内层循环范围`n-i-1`:每轮减少已排序区的比较 5. **执行过程示例**(初始数组:[5, 3, 8, 1]): ``` 第1轮: [3,5,8,1] → [3,5,1,8] → [3,1,5,8] → [1,3,5,8] 第2轮: 检测无交换,提前结束 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值