?>冒泡排序(Bubble Sort)
也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
1、原理
每一趟只能确定将一个数归位。即第一趟只能确定将末位上的数归位,第二趟只能将倒数第 2 位上的数归位,依次类推下去。 如果有 n 个数进行排序,只需将 n-1 个数归位,也就是要进行 n-1 趟操作。 而 “每一趟 ” 都需要从第一位开始进行相邻的两个数的比较,将较大的数放后面, 比较完毕之后向后挪一位继续比较下面两个相邻的两个数大小关系,重复此步骤,直到最后一个还没归位的数。
2、动图演示
!>什么时候最快:
当输入的数据已经是正序时(都已经是正序了,我还要你冒泡排序有何用啊)。
!>什么时候最慢:
当输入的数据是反序时(写一个 for 循环反序输出数据不就行了,干嘛要用你冒泡排序呢,我是闲的吗)。
3、代码实现
3.1 JavaScript 代码实现
function bubbleSort(arr) { var len = arr.length; for (var i = 0; i < len - 1; i++) { for (var j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j+1]) { // 相邻元素两两对比 var temp = arr[j+1]; // 元素交换 arr[j+1] = arr[j]; arr[j] = temp; } } } return arr; }
3.2 Python 代码实现
def bubbleSort(arr): for i in range(1, len(arr)): for j in range(0, len(arr)-i): if arr[j] > arr[j+1]: arr[j], arr[j + 1] = arr[j + 1], arr[j] return arr
3.3 Go 代码实现
func bubbleSort(arr []int) []int { length := len(arr) for i := 0; i < length; i++ { for j := 0; j < length-1-i; j++ { if arr[j] > arr[j+1] { arr[j], arr[j+1] = arr[j+1], arr[j] } } } return arr }
3.4 Java 代码实现
public static void BubbleSort(int [] arr){ int temp;//临时变量 for(int i=0; i<arr.length-1; i++){ //表示趟数,一共arr.length-1次。 for(int j=arr.length-1; j>i; j--){ if(arr[j] < arr[j-1]){ temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; } } } }
4、优化(Java)
针对问题(1):
( 发现整个数列已经是有序的了
)– 数据的顺序排好之后,冒泡算法仍然会继续进行下一轮的比较,直到arr.length-1次,后面的比较没有意义的。
方案:
-
设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。
-
这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。
public static void BubbleSort1(int [] arr){ if (arr == null || arr.length < 2) { return arr; } int temp;//临时变量 boolean flag;//是否交换的标志 for(int i=0; i<arr.length-1; i++){ //表示趟数,一共arr.length-1次。 flag = true; for(int j=arr.length-1; j>i; j--){ if(arr[j] < arr[j-1]){ temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; flag = false;//有元素交换,所以不是有序,标记变为false } } //一趟下来是否发生位置交换,如果没有交换直接跳出大循环 if(flag) break; } }
针对问题(2):
( 发现整个数列有序区的界定
)– 数据的顺序排好之后, 在一轮排序后,发现后面其实又是有序数列了,但是还是要每一次两两相比,这样也白白比较了很多次了 。
图例:
方案:
-
记录最后一次交换的位置
public static int[] BubbleSort(int[] arr) { if (arr == null || arr.length < 2) { return arr; } //记录最后一次交换的位置 int lastExchangeIndex = 0; //无序数列的边界,每次比较只需要比到这里为止 int sortBorder = arr.length - 1; for (int i = 0; i < arr.length - 1; i++) { boolean isSorted = true;//有序标记,每一轮的初始是true for (int j = 0; j < sortBorder; j++) { if (arr[j + 1] < arr[j]) { isSorted = false;//有元素交换,所以不是有序,标记变为false int t = arr[j]; arr[j] = arr[j+1]; arr[j+1] = t; lastExchangeIndex = j; } } sortBorder = lastExchangeIndex //一趟下来是否发生位置交换,如果没有交换直接跳出大循环 if(isSorted ) break; } return arr; }