本文专门写给萌新看,大佬别捶我 qwq
转自我自己的Blog 传送门
友情提示:到我的Blog食用效果更佳,不过加载速度可能会比较拉胯 XD
冒泡排序
照理先抄他一段百度百科:
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
基本思想
aaaaaaz! 不愧是度娘,能把这么简单的一个算法写这么长的介绍,下面我简单说一下:
你想想,我们要把一串数字进行排序,是不是可以每相邻两个进行一次比较,如果不符合当前的排序规则,就把这两个数字进行交换,那么不可以继续交换的时候,是不是就排完了?
从此引出:
冒泡排序基本思想:每次比较两个相邻的元素,如果这两个元素的顺序错误就把这两个元素交换
举个栗子
我们现在需要把这一个数列【5
4
3
2
1
】变成从小到大的顺序
根据冒泡排序的基本思想,我们从头开始依次比较:([]代表比较,如果不符合 $ 前者<后者 $ (因为要变成从小到大,所以 $ 前者 $ 肯定不会比 $ 后者 $ 大),就把它们交换)
1: [5 4] 3 2 1 比较5与4,因为5<4不正确,所以交换
2: 4 [5 3] 2 1 比较5与3,因为5<3不正确,所以交换
3: 4 3 [5 2] 1 比较5与2,因为5<2不正确,所以交换
4: 4 3 2 [5 1] 比较5与1,因为5<1不正确,所以交换
4 3 2 1 5 第一轮的结果
放个图片解释一下:
这样,重复很多次这样的操作,就可以得到像这样的数列:【1
2
3
4
5
】
如果继续对这个数列进行上面的操作,你会发现不管操作多少次,数列都不会有变动了,这就是所谓的排序完成了
那么这里就有一个值得思考的问题了,我们到底应该执行几次从头到尾的比较?这其实就跟需要排序的数列有关了,如果数列像上面一样(把一个从大到小的数列排序为从小到大的数列),那么就需要 数列中有的数字的个数n - 1
轮(可以手动模拟一次,不难发现上面的栗子需要四轮才可以排序好),其他情况就不大好判断了,所以我们每次交换完,需要判断一下这个数列是不是已经排好序了,不然可能会进行多余的操作。
交换
哦哦哦,忘记说交换了
把两个变量中的数值交换过来,其实也有很多很多种方法,这里就列举几种(其实只需要记住第一种)
中介变量
我们可以用一个中介变量t
来存储其中的一个变量a
的值,然后把已经把值存到中介变量的变量a
赋值为另外一个变量b
的值,然后再把另外一个变量赋值为中介变量
代码:
void Swap(int & a,int & b) {
int t=a;
a=b;
b=a;
}
加减
我们可以用加减法的一些性质来做到交换,可能看上去不大好理解,为了方便理解,我们把默认把要交换的值设置为x
和y
(还是不理解可以拿)
下面是两个版本:
void Swap(int & a,int & b) {
a=a+b; // a=x+y b=y
b=a-b; // a=x+y b=x+y-y=x
a=a-b; // a=x+y-x=y b=x;
}
void Swap(int & a,int & b) {
a=a-b; // a=x-y b=y
b=a+b; // a=x-y b=(x-y)+y=x
a=b-a; // a=x-(x-y)=y b=x;
}
模板代码
上代码:
const int maxn=1e5; // 数组大小
int a[maxn]; // 数组a 从下标1 开始存数字
void swap(int & a,int & b) { int t=a;a=b,b=t; }
void BubbleSort(int n) { // 排序 在数组 a 中从 1-n 的数字
bool Sorted=false; // 排序完成的标志
while(!Sorted) {
//
for(int i=2;i<=n;i++) {
if(a[i-1]>a[i]) {
swap(a[i-1],a[i]);
}
}
// 判断是否排序完成
Sorted=true; // 默认当成排序完成了,如果检查的时候发现没完成再把标志变为未完成
for(int i=2;i<=n;i++) {
if(a[i-1]>a[i]) {
Sorted=false;
}
}
}
return ;
}
题目
题目要求我们输出相邻元素 交换(划重点 这是用冒泡排序的原因)的次数,那么就需要对上面的模板进行一定的修改……
代码:
const int maxn=1e4+11; // 防止溢出 习惯性写上比题目范围大一点的数字就行
int a[maxn];
int BubbleSort(int n) // 返回交换的次数
int count=0; // 计数器,每次交换都加一
bool Sorted=false;
while(!Sorted) {
for(int i=2;i<=n;i++) {
if(a[i-1]>a[i]) {
swap(a[i-1],a[i]);
count+=1; // 计数
}
}
Sorted=true;
for(int i=2;i<=n;i++) {
if(a[i-1]>a[i]) {
Sorted=false;
}
}
}
return count;
}