基本思想:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
冒泡排序的示例:
算法的实现:
public void bubbleSort(int[] a) {
for(int i = a.length - 1; i > 0; i--) {
for(int j = 0; j < i; j++) {
if(a[j] > a[j+1])
//交换,具体实现略
swap(a, j, j+1);
}
}
}
算法优化(一):设置是否交换的标志exchange
我们可以假设一种场景,比如 8 1 2 3 5 7,进行一次排序之后,结果就变成了 1 2 3 5 7 8,那我们还有必要再像上面代码里那样继续循环下去吗?肯定没有必要了,因为这已经是最终结果了。
那针对上面的代码,我们优化的点主要在于:假如某一趟排序之后已经有序,我们需要减少排序的趟数。否则就做了很多无用功。
针对这个问题,我们可以考虑在算法中加入一个 变量,来标识该轮有没有进行数据的交换,若在某一趟排序中未发现数据位置的交换,则说明待排序的无序区中所有的项均已满足排序后的结果。那么就没有必要再次排序下去了。可以如下改造:
#include"stdio.h"
#include <string.h>
int bubbleSort(int a[], int num)
{
int exchange;
int n = 0; //用来表示一共进行了多少次外层排序
int i, j;
int swap;
for(i = num - 1; i > 0; i--)
{
exchange = 0;
for(j = 0; j < i; j++)
{
if(a[j] > a[j+1]) {
swap = a[j];
a[j] = a[j+1];
a[j+1] = swap;
exchange = 1;
}
}
++n;
if(!exchange)
return n;
}
return n;
}
int main()
{
int b[] = {3, 2, 1, 4, 5};
printf(" %d ,%d \n", sizeof(b)/sizeof(int), bubbleSort(b, 5));
return 0;
}
算法优化(二):设置最后一次交换的位置
这种方式可以获得最好情况,即已经排号序了,第一次就可以结束
设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
改进后算法如下:
#include <stdio.h>
#include <iostream>
using namespace std;
void print(int a[],int i)
{
cout<<i <<" : ";
for(int j= 0; j<10; j++)
{
cout<<a[j] <<" ";
}
cout<<endl;
}
void Bubble_2( int r[], int n) {
int i= n -1, j; //初始时,最后位置保持不变
int tmp;
while ( i > 0)
{
int pos= 0; //每趟开始时,无记录交换
for (j = 0; j < i; j++)
{
if (r[j] > r[j+1]) {
pos = j; //记录交换的位置
tmp = r[j];
r[j] = r[j+1];
r[j+1] = tmp;
}
}
i = pos; //为下一趟排序作准备
print(r, i);
}
}
int main()
{
int H[10] = {3,1,5,7,2,4,9,6,10,8};
Bubble_2(H,10);
return 0;
}
运行结果:
8 : 1 3 5 2 4 7 6 9 8 10
7 : 1 3 2 4 5 6 7 8 9 10
1 : 1 2 3 4 5 6 7 8 9 10
0 : 1 2 3 4 5 6 7 8 9 10
算法优化(三):同时交换最大值和最小值
传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,我们考虑利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排序趟数几乎减少了一半。
改进后的算法实现为:
#include <stdio.h>
#include <iostream>
using namespace std;
void print(int a[],int i)
{
cout<<i <<" : ";
for(int j= 0; j<10; j++)
{
cout<<a[j] <<" ";
}
cout<<endl;
}
void Bubble_2 ( int r[], int n){
int low = 0;
int high= n -1; //设置变量的初始值
int tmp,j;
while (low < high)
{
for (j= low; j< high; ++j) //正向冒泡,找到最大者
{
if (r[j] > r[j+1]) {
tmp = r[j];
r[j] = r[j+1];
r[j+1] = tmp;
}
}
--high; //修改high值, 前移一位
for (j = high; j>low; --j) //反向冒泡,找到最小者
{
if (r[j] < r[j-1]) {
tmp = r[j];
r[j] = r[j-1];
r[j-1] = tmp;
}
}
++low; //修改low值,后移一位
print(r, low);
}
}
int main()
{
int H[10] = {3,1,5,7,2,4,9,6,10,8};
Bubble_2(H,10);
return 0;
}
运行结果:
1 : 1 2 3 5 4 6 7 8 9 10
2 : 1 2 3 4 5 6 7 8 9 10
3 : 1 2 3 4 5 6 7 8 9 10
4 : 1 2 3 4 5 6 7 8 9 10
5 : 1 2 3 4 5 6 7 8 9 10