上一节讲述了最简单快速的排序算法——桶排序,桶排序算法有一个很要命的缺点是浪费空间,相反,它的时间复杂度为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;
}