基础写法
冒泡排序思想:泡泡一直向上冒,冒到不能冒的位置。即每次比较两个相邻元素,如果顺序不对就交换,这样一轮交换就能确定当前最大/小值。
假设数组,按照从小到大排序,如果第1个元素大于第2个元素,则交换两个元素,一直到第n-1个元素和第n个元素比较,那么一轮结束,第n个元素一定是该数组的最大值,接下来第2轮对进行相同操作,第n-1个元素一定是第2大元素。一共需要n-1轮比较。
以下代码全部按照从小到大排序。
void bubblesort(vector<int> &numbers)
{
int len = numbers.size();
if(len <= 0) return;
int swapTmp;
for(int i = 1; i < len; i++) //确定比较轮数
{
for(int j = 0; j < len-i; j++) //比较范围
{
if(numbers[j] > numbers[j+1])
{
swapTmp = numbers[j];
numbers[j] = numbers[j+1];
numbers[j+1] = swapTmp;
}
}
}
}
优化
优化1
在排序过程中,可能不需要n-1轮就能排好序,比如0 1 2 3 4 5 8 6,只需要一轮就能结束。
加入一个标记变量,如果当前轮没有进行任何交换,就结束排序。
void bubblesort(vector<int> &numbers)
{
int len = numbers.size();
if(len <= 0) return;
int swapTmp;
int flag; //加入flag进行标记
for(int i = 1; i < len; i++)
{
flag = 0;
for(int j = 0; j < len-i; j++)
{
if(numbers[j] > numbers[j+1])
{
swapTmp = numbers[j];
numbers[j] = numbers[j+1];
numbers[j+1] = swapTmp;
flag = 1;
}
}
if(flag == 0) //说明没有任何交换,提前结束
return;
}
}
优化2
对于数组,第一轮比较的范围是1 ~ n(第n-1个元素和第n个元素比较),第二轮比较的范围是1 ~ n-1,第三轮比较的范围是1~n-2……其实第k轮可能没必要从1到n-k+1。
引入一个变量nextpos,记录上轮排序最后交换的位置,下一轮排序只需要从1到nextpos即可。
void bubblesort(vector<int> &numbers)
{
int len = numbers.size();
if(len <= 0) return;
int swapTmp;
int flag; //加入flag进行标记
int nextpos = len-1, posTmp = len-1; //引入变量记录上次最后交换的位置
for(int i = 1; i < len; i++) //确定比较轮数
{
flag = 0;
if(i != 1)
nextpos = posTmp;
for(int j = 0; j < nextpos; j++) //比较范围
{
if(numbers[j] > numbers[j+1])
{
swapTmp = numbers[j];
numbers[j] = numbers[j+1];
numbers[j+1] = swapTmp;
posTmp = j;
flag = 1;
}
}
if(flag == 0) //说明没有任何交换,提前结束
return;
nextpos = posTmp;
}
}
优化3
基本思想是一轮排序确定两个值,正向扫描找到最大值交换到最后,反向扫描找到最小值交换到最前面。举例,下面是一轮排序的结果:
一个排序的例子 |
---|
原始数组序列:1 2 3 4 5 6 0 |
正向扫描结束:1 2 3 4 5 0 6 |
反向扫描step1:1 2 3 4 0 5 6 |
反向扫描step2:1 2 3 0 4 5 6 |
反向扫描step3:1 2 0 3 4 5 6 |
反向扫描step4:1 0 2 3 4 5 6 |
反向扫描结束:0 1 2 3 4 5 6 |
void bubblesort(vector<int> &numbers)
{
int len = numbers.size();
if(len <= 0) return;
int swapTmp;
int flag; //加入flag进行标记
int nextpos = len-1, posTmp = len-1;
for(int i = 1; i < len; i++) //确定比较轮数
{
flag = 0;
if(i != 1)
nextpos = posTmp;
for(int j = 0; j < nextpos; j++) //正向扫描
{
if(numbers[j] > numbers[j+1])
{
swapTmp = numbers[j];
numbers[j] = numbers[j+1];
numbers[j+1] = swapTmp;
posTmp = j;
flag = 1;
}
}
if(flag == 0)
return;
for(int j = posTmp; j > 0; j--) //反向扫描
{
if(numbers[j] > numbers[j-1])
{
swapTmp = numbers[j];
numbers[j] = numbers[j+1];
numbers[j+1] = swapTmp;
flag = 1;
}
}
if(flag == 0)
return;
nextpos = posTmp;
}
}
参考
[1] 冒泡排序以及三种优化
注:很大程度上参考了这位同学的思想,同时结合评论讨论对原来代码中的一些错误做了修改。
来源:https://blog.csdn.net/wyh7280/article/details/98964847