冒泡排序法

冒泡排序

​ 简化版的桶排序不仅仅有之前说过的遗留问题,更要命的是:它非常浪费空间,例如需要排序的范围是0~2100000000,那么你就必须要申请2100000001个变量,也就是说你要申请一个这样的数组 int a[2100000001]。因为我们需要使用2100000001个桶来存储这个范围里每一个数的出现的次数,即便我只给你5个数字或者1个数字,你还是需要申请一个这么大的数组来存储。这样就太浪费空间了。还有,如果现在需要排序的不再是一些整数,而是一些小数呢?如果要将这些小数进行排序那么要怎么办呢?下面就是一种排序算法:冒泡算法,它可以很好的解决这个问题。

冒泡排序的基本思想就是:每次比较两个相邻的元素,如果他们的顺序有错误就把他们的顺序进行交换。

​ 例如,我们需要将12 35 99 18 76这5个数进行从大到小得到排序。既然是从大到小的排序,也就是说越小越靠后。

​ 首先比较第1位和第2位的大小,现在第1位是12,第2位时35,发现12比35要小,因为我们希望越小的数越靠后,因此需要交换这两个数的位置。交换之后这两个数的位置是35 12 99 18 76。

​ 按照刚刚的方法,继续比较第2个数和第3个数的位置。最后比较完这一轮之后,5个数的顺序为35 99 18 76 12。

​ 然后重复刚刚的过程,再次从1位开始比较,然后5个数的顺序为 99 35 76 18 12。

​ 第三轮再继续比较,5个数的顺序为99 76 35 18 12。

​ 然后就到了最后一轮的,第四轮,当然到这里就有人会问了,这不是已经排序好了吗,还要继续干嘛,这里纯属是一个巧合,你如果用别的数字去进行排序,可能结果就不会是这样还需要继续排序。

​ 冒泡排序的原理是:每一趟只确定一个数归位。即第一躺只能确定末位的数字归位,第二趟只能确定倒数第2位的数字归位,第三趟只能确定倒数第3位的数字归位,而现在前面还有两个数字没有归位,所以我们仍然需要再进行第4躺排序。

​ 最后总结一下:如果有n个数字需要进行排序,只需要将n-1个数归位,也就是说要进行n-1躺排序。而每一趟都需要从第1位开始进行相邻两个数大小的比较,重复此步骤,直到最后一个尚未归位的数,已经归位的数则无需再进行比较。

#include <stdio.h>
int main()
{
    int arr[100], i, j, t, n;
    scanf("%d", &n); // 输入一个数,表示接下来将输入多少个数需要排序
    for (i = 1; i <= n; i++) {
        scanf("%d", &arr[i]);
    }
    // 冒泡排序
    for (i = 0; i <= n - 1; i++) {
        for (j = 0; j = n - i - 1; j ++) {
            if (arr[j] > arr[j + 1]) {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;
            }
        }
    }
}

完整的函数与验证排序的方式

#include <stdio.h>
void bubble_sort(int arr[], int len) { // 将冒泡排序写入函数
        int i, j, temp;
        for (i = 0; i < len - 1; i++)
                for (j = 0; j < len - 1 - i; j++)
                        if (arr[j] > arr[j + 1]) {
                                temp = arr[j];
                                arr[j] = arr[j + 1];
                                arr[j + 1] = temp;
                        }
}
int main() {
        int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
        int len = (int) sizeof(arr) / sizeof(*arr);
        bubble_sort(arr, len);
        int i;
        for (i = 0; i < len; i++)
                printf("%d ", arr[i]);
        return 0;
}

如果要对前面的简化版的桶排序的遗留问题进行处理则可以使用以下方法:

#include <stdio.h>

struct student
{
    char name[21];
    double score;
}; // 此处创建一个结构体,用于存储名字和对应的成绩

int main()
{
    struct student a[100], t;
    int i, j, n;
    scanf("%d", &n);
    
    for (i = 1; i<= n; i++) {
        scanf("%s %d", a[i], &a.score);
    }
    
    for (i = 1; i <= n-1; i++) {
        for (j = 1; j <= n - 1; j++)
            if (a[j].score < a[j + 1].score) {
                t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }
    }
    for (i = 1; i <= n; i++) {
        printf("%s, %lf\n", a[i].name, a[i].score);
    }
}

冒泡排序的核心是双重嵌套循环。不难看出冒泡排序的时间复杂度是O(N2)。这时一个非常高的时间复杂度。冒泡排序很早在1956年就有人在开始研究了,之后很多人尝试过对冒泡排序进行改进,但结果都令人很失望。那么你可能要问:有没有比冒泡排序更好的排序算法了呢,下面会看到快速排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值