冒泡排序
冒泡排序(Buble Sort)作为一种简单的排序算法,比较容易理解,所以初学算法时候对冒泡排序理解清楚对于以后学习更加复杂的算法会有不小的帮助,所以学习一下冒泡排序还是非常有必要的.
冒泡排序大致想法就是:从第一个开始比较相邻两个元素的值,如果它们的顺序不符合要求就换过来.直到最后一个元素,将最大或者最小的元素沉底.
冒泡排序具体运作可以分为以下几步(以由小到大排列为例):
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
冒泡排序的动画演示如下
下面是Java的冒泡排序:
public class BubbleSort{
public static void main(String[] args){
int score[] = {9,4,5,6,8,3,2,7,10,1};
for (int i = 0; i < score.length -1; i++){ //最多做n-1趟排序
for(int j = 0 ;j < score.length - 1 - i; j++){ //对当前无序区间score[0......length-i-1]进行排序(j的范围很关键,这个范围是在逐步缩小的,建议大家写成score.length-1-i这样比较容易理解每趟比较结束后j的范围)
if(score[j] > score[j + 1]){ //把大的值交换到后面
int temp = score[j + 1];
score[j + 1] = score[j];
score[j] = temp;
}
}
System.out.print("第" + (i + 1) + "次排序结果:");
for(int a = 0; a < score.length; a++){
System.out.print(score[a] + "\t");
}
System.out.println("");
}
System.out.print("最终排序结果:");
for(int a = 0; a < score.length; a++){
System.out.print(score[a] + "\t");
}
}
}
可能大家不明白我为什么要没排一次输出一次,但是如果你做了,你就会发现一些问题,请看下图:
看到这张图,首先,来看冒泡的特点,观察每次排序最后一个数,就是我们需要沉底的数,每趟比较结束后都将本趟比较中最大的数排到本趟的最后.
其次,我们要知道,冒泡排序的比较次数非常的多,一共比较n(n-1)/2次.
局部冒泡排序
概念:对于N个无序数据,我们在进行一趟冒泡排序时,如果第k个数据和第k+1个数据逆序(不符合排序的要求),那么对第k+1个数据进行一趟向前的冒泡排序,使其移动到合适的位置,也就是说让前面k+1个数据调节为正序。因为这种冒泡法只对前k+1个数据冒泡处理,所以我们称它为——局部冒泡。
看代码:
public class PartBubbleSort{
public static void main(String[] args){
int score[] = {9,4,5,6,8,3,2,7,10,1};
for (int i = 0; i < score.length -1; i++){ //最多做n-1趟排序
if(score[i]>score[i + 1])
{
int j = 0;
int temp = 0;
j = i + 1;
while(j > 0 && score[j] < score[j - 1])
{
temp=score[j];
score[j]=score[j - 1];
score[j - 1] = temp;
j--;
}
}
System.out.print("第" + (i + 1) + "次排序结果:");
for(int a = 0; a < score.length; a++){
System.out.print(score[a] + "\t");
}
System.out.println("");
}
System.out.print("最终排序结果是:");
for(int a = 0; a < score.length; a++){
System.out.print(score[a] + "\t");
}
}
}
局部冒泡的思想是对于一开始不符合要求的一组才比较,局部冒泡排序算法至少需进行1 趟扫描, 至多需进行n- 1 趟扫描(其中只有一趟扫描是全局的, 其余趟扫描都是局部扫描, 扫描范围相对小得多。即在待排序数据初始有序( 正序) 情况下, 关键字的比较次数为n- 1, 数据的移动次数为0; 在待排序数据初始逆序的情况下, 关键字的比较次数为n ( n- 1) / 2, 最坏情况下, 每一次比较均会发生数据的交换, 即移动次数为3 n( n- 1) / 2。显然局部冒泡排序与冒泡排序算法具有相同的时间复杂度, 并且在正序和逆序的情况下, 所需的关键字的比较次数和移动次数完全相同。
下面是输出的结果:
那么局部冒泡的优势在哪里呢?其实,局部冒泡还是胜在比较次数看下面的对比:
注:测试所用数据均为随机产生的32 位非负整数,由于测试程序的统计量不是运行时间, 所以表1 中的测试结果不依赖于具体计算机的软、硬件等环境因素, 而仅与算法有关。(表摘自点击打开链接)
由上图可见,局部冒泡法的平均移动次数等于冒泡法,但是局部冒泡法的平均比较次数小于冒泡法。