前面两篇介绍了两个非常简单和基础的排序算法——选择排序和插入排序,除了这两个,冒泡排序也是非常简单的一种排序算法。同样,本篇主要从“基本原理、排序流程、核心代码、算法性能、稳定性、参考代码”等几个方面介绍这一算法。
基本原理:依次比较两个相邻元素的大小,如果前一个元素大于(或小于)后一个元素,则两个元素交换位置。这样每一趟都能确定一个最大(或最小)的元素,每一趟都能把最大(或最小)的元素放到最后,直到所有元素都有序为止。
排序流程:以下以序列:5 3 0 4 1 9 7 2 6 8为例,加粗元素表示每一趟参与比较的元素,未加粗元素表示已经排好的元素(未参与比较),红色元素表示每一趟排好的最大元素。
趟数 | 排序前 | 排序后 | 说明 |
1 | 5 3 0 4 1 9 7 2 6 8 | 3 0 4 1 5 7 2 6 8 9 | 9元素最大,移动到最后面位置,此时9元素位置已定 |
2 | 3 0 4 1 5 7 2 6 8 9 | 0 3 1 4 5 2 6 7 8 9 | 8元素最大,移动到9元素前面位置,8元素位置已定 |
3 | 0 3 1 4 5 2 6 7 8 9 | 0 1 3 4 2 5 6 7 8 9 | 7元素最大,移动到8元素前面位置,7元素位置已定 |
4 | 0 1 3 4 2 5 6 7 8 9 | 0 1 3 2 4 5 6 7 8 9 | 6元素最大,移动到7元素前面位置,6元素位置已定 |
5 | 0 1 3 2 4 5 6 7 8 9 | 0 1 2 3 4 5 6 7 8 9 | 5元素最大,移动到6元素前面位置,5元素位置已定 |
6 | 0 1 2 3 4 5 6 7 8 9 | 0 1 2 3 4 5 6 7 8 9 | 4元素最大,移动到5元素前面位置,4元素位置已定 |
7 | 0 1 2 3 4 5 6 7 8 9 | 0 1 2 3 4 5 6 7 8 9 | 3元素最大,移动到4元素前面位置,3元素位置已定 |
8 | 0 1 2 3 4 5 6 7 8 9 | 0 1 2 3 4 5 6 7 8 9 | 2元素最大,移动到3元素前面位置,2元素位置已定 |
9 | 0 1 2 3 4 5 6 7 8 9 | 0 1 2 3 4 5 6 7 8 9 | 1元素最大,移动到2元素前面位置,1元素位置已定 |
最终排序结果为:0 1 2 3 4 5 6 7 8 9。最后一趟由于只比较了前两个元素,后面所有元素都已有序,所以此趟结束之后,序列已经有序了。需要注意的是,每一趟排序都能确定最大(或最小)的元素,但发生移动的元素可能不仅仅是最大(或最小)的元素,比如第一趟中5元素的位置发生改变。可以看出,如果序列长度为N,则总共进行了N-1趟排序,每一趟都能确定一个元素,所以下一趟参与比较的元素会比上一趟少一个。
核心代码:以Java为例。
public static void sort(int[] a){ int n = a.length; //序列长度 for (int i = 0; i < n-1; i++){ //排序趟数 for (int j = 0; j < n-i-1; j++){ if (a[j + 1] < a[j]){ int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } }
算法性能:对于所有元素都相等或者已经有序的序列,只会进行(N-1)+(N-2)+……+1=N(N-1)/2次比较,不会发生任何移动;对于逆序序列,同样会进行N(N-1)/2次比较,但每次比较都会交换元素,每次交换都会移动两个元素,所以会有N(N-1)次移动。总的来说,时间复杂度为O(N2),空间复杂度为O(1)。
稳定性:冒泡排序就是不断把大的元素移动到序列后面的过程,每次比较都是相邻的两个元素比较,交换也是相邻的两个元素交换。所以如果序列中有两个或多个元素相等,排序的时候不会发生交换;如果两个或多个相等的元素没有相邻,那么即使通过前面的两两交换把它们相邻起来,它们之间也不会发生交换,这样相等的元素相对位置并没有改变,所以冒泡排序是稳定的。
参考代码:以Java为例。
import java.util.Random; /* * 冒泡排序 */ public class BubbleSort { public static void sort(int[] a){ int n = a.length; //序列长度 for (int i = 0; i < n-1; i++){ //排序趟数 for (int j = 0; j < n-i-1; j++){ if (a[j + 1] < a[j]){ int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } } public static void main(String[] args) { Random random = new Random(); int[] arg1 = new int[20]; for(int n=0;n<20;n++){ //从[0-100]中生成20个随机数 arg1[n] = random.nextInt(100); } System.out.println("排序前:"); for (int i = 0; i < arg1.length; i++) { System.out.print(arg1[i]+" "); } System.out.println("\n排序后:"); long startTime = System.currentTimeMillis(); //获取开始时间 sort(arg1); long endTime = System.currentTimeMillis(); //获取结束时间 for (int i = 0; i < arg1.length; i++) { System.out.print(arg1[i]+" "); } System.out.println("\n排序时长:"+(endTime-startTime)+"ms"); } }
运行结果:
排序前: 83 13 36 11 58 75 68 43 73 72 24 81 98 14 27 23 1 46 60 3 排序后: 1 3 11 13 14 23 24 27 36 43 46 58 60 68 72 73 75 81 83 98 排序时长:0ms
zhuanzi http://www.cnblogs.com/Y-oung/p/7820294.html