排序算法(二) 冒泡排序

本文详细介绍了冒泡排序算法的工作原理,并通过实例展示了如何对整数和小数进行排序。冒泡排序是一种简单直观的排序算法,虽然效率较低,但易于理解。文章还提供了C语言的代码实现,用于对整数数组进行排序,并给出了针对成绩排序的结构体解决方案。

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

上一节讲述了最简单快速的排序算法——桶排序,桶排序算法有一个很要命的缺点是浪费空间,相反,它的时间复杂度为O(M+N),是一种空间换时间的策略

关于桶排序算法参照博文:https://blog.csdn.net/qq_37120369/article/details/118916335

上一节使用桶排序算法排序的是整数,如果现在需要排序的不再是整数而是一些小数,比如将 5.56789,2.12,1.1,3.123,4.1234 这五个数进行从小大排序又该怎么办呢?
现在我们来学习另一种新的排序算法:冒泡排序。它可以很好的解决这两个问题。
1、问题描述
将 12 35 99 18 76 这 5 个数进行从大到小进行排序。
2、解决思路
首先比较第 1 位和第 2 位的大小,现在第 1 位是 12,第 2 位是 35。发现 12 比 35 要小,因为我们希望越小越靠后嘛,因此需要交换这两个数的位置。交换之后这 5 个数的顺序是 35 12 99 18 76。
按照刚才的方法,继续比较第 2 位和第 3 位的大小,第 2 位是 12,第 3 位是 99。12 比 99 要小,因此需要交换这两个数的位置。交换之后这 5 个数的顺序是 35 99 12 18 76。
根据刚才的规则,继续比较第 3 位和第 4 位的大小,如果第 3 位比第 4 位小,则交换位置。交换之后这 5 个数的顺序是 35 99 18 12 76。
最后,比较第 4 位和第 5 位。4 次比较之后 5 个数的顺序是 35 99 18 76 12。
经过 4 次比较后我们发现最小的一个数已经就位(已经在最后一位,请注意 12 这个数的移动过程),是不是很神奇。现在再来回忆一下刚才比较的过程。每次都是比较相邻的两个数,如果后面的数比前面的数大,则交换这两个数的位置。一直比较下去直到最后两个数比较完毕后,最小的数就在最后一个了。就如同是一个气泡,一步一步往后“翻滚”,直到最后一位。所以这个排序的方法有一个很好听的名字“冒泡排序”。

 

说到这里其实我们的排序只将 5 个数中最小的一个归位了。每将一个数归位我们将其称为“一趟”。下面我们将继续重复刚才的过程,将剩下的 4 个数一一归位。
好现在开始“第二趟”,目标是将第 2 小的数归位。
首先还是先比较第 1 位和第 2 位,如果第 1 位比第 2 位小,则交换位置。交换之后这 5 个数的顺序是 99 35 18 76 12。
接下来你应该都会了,依次比较第 2 位和第 3 位,第 3 位和第 4 位。注意此时已经不需要再比较第 4 位和第 5 位。因为在第一趟结束后已经可以确定第 5 位上放的是最小的了。第二趟结束之后这 5 个数的顺序是 99 35 76 18 12。
“第三趟”也是一样的。第三趟之后这 5 个数的顺序是 99 76 35 18 12。
现在到了最后一趟“第四趟”。有的同学又要问了,这不是已经排好了吗?还要继续?当然,这里纯属巧合,你可以用别的数试一试可能就不是了。你能找出这样的数据样例来吗?请试一试。
“冒泡排序”原理是:每一趟只能确定将一个数归位。即第一趟只能确定将末位上的数(既第 5 位)归位,第二趟只能将倒数第 2 位上的数(既第 4 位)归位,第三趟只能将倒数第 3 位上的数(既第 3 位)归位,而现在前面还有两个位置上的数没有归位,因此我们仍然需要进行“第四趟”。
“第四趟”只需要比较第 1 位和第 2 位的大小。因为后面三个位置上的数归位了,现在第 1 位是 99,第 2 位是76,无需交换。这 5 个数的顺序不变仍然是 99 76 35 18 12。到此排序完美结束了,5 个数已经有 4 个数归位,那最后一个数也只能放在第 1 位了。
3、代码实现
#include <stdio.h>
int main()
{
  #define LEN 5
  int a[LEN]={12,35,99,18,76},i,j,t;
  
  //冒泡排序的核心部分
  for(i=0;i<LEN-1;i++) //n个数排序,只用进行n-1趟
  {
    for(j=0;j<LEN-1-i;j++) 
    {
      if(a[j]<a[j+1]) //比较大小并交换
      { 
        t=a[j]; 
        a[j]=a[j+1]; 
        a[j+1]=t; 
      }
    } 
  }

  for(i=0;i<LEN;i++) //输出结果
    printf("%d ",a[i]);

  getchar();getchar();
  return 0;
}

4、上一节遗留问题的解决方案

问题:如何根据成绩将人名排序。

解决方案:可以创建一个结构体,用来存储人名和分数据。最后再创建一个结构体数据用来存放多名学生的数据。

#include <stdio.h>
#define LEN 5
struct student
{
  char name[21];
  char score;
};//这里创建了一个结构体用来存储姓名和分数

int main()
{
  struct student t , a[LEN] ={{"huhu",5},{"haha",3},{"xixi",5},{"hengheng",2},{"gaoshou",8}};
  int i,j;
  
  //按分数从高到低进行排序
  for(i=0;i<LEN-1;i++)
  {
    for(j=0;j<LEN-1-i;j++)
    {
      if(a[j].score<a[j+1].score)//对分数进行比较
      { 
         t=a[j]; 
         a[j]=a[j+1]; 
         a[j+1]=t; 
      }
    } 
  }

  for(i=0;i<LEN;i++)//输出人名
    printf("%s\n",a[i].name);
  
  getchar();getchar();
  return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Rookie Linux

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

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

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

打赏作者

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

抵扣说明:

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

余额充值