详解Java算法之冒泡排序(Bubble Sorting)
冒泡排序基本介紹
冒泡排序(Bubble Sorting)的基本思想是通過對待排序序列從前向后(從下表較小的元素開始),以此比較相鄰元素的值,若發現逆序則交換,使值較大的元素逐漸從前向后部,就像水底下的氣泡一樣逐漸向上冒。
文章目錄
- 冒泡排序基本介紹
- 冒泡排序應用實例
- 代碼實現
- 排序優化
- 性能測試
冒泡排序應用實例
我們舉一個具體的案例來說明冒泡排序法,我們將幾個無序的數:3,6,4,2,11,10,5 使用冒泡排序法將其排成一個從小到大的有序數列。
看上面的圖解可能有些小伙伴不好理解,不過沒關系下面我們更詳細的給大家列出排序細節。
原始數組為:3,6,4,2,11,10,5 下面進行第一趟排序
第一趟排序的最終結果為:3,4,2,6,10,5,11 下面進行第二趟排序
需要注意的是每趟運行過后最后一個數就會被確認下來,不在進行比較交換。現在我們重新回到上方排序交換圖,是不是思路一下就清晰起來了?
冒泡排序規則總結:
- 一共進行數組大小 -1次循環
- 每一趟排序的次數在逐漸的減小
- 如果我們發現在某趟排序中,沒有發生一次交換可以提前結束排序,這個就是優化。
代碼實現
原始數組為:3,6,4,2,11,10,5 下面進行第一趟排序
public static void main(String[] args) {int arr[] = {3, 6, 4, 2, 11, 10, 5};//為了容易理解,我們把冒泡排序的演變過程,給大家展示一下。//第一趟排序,就是將最大的數排在最后int temp = 0; //臨時變量for (int j = 0; j < arr.length - 1; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("第一趟排序后的數組");System.out.println(Arrays.toString(arr));}第一趟排序的最終結果為:3,4,2,6,10,5,11 下面進行第二趟排序
public static void main(String[] args) {int arr[] = {3, 6, 4, 2, 11, 10, 5};//為了容易理解,我們把冒泡排序的演變過程,給大家展示一下。//第一趟排序,就是將最大的數排在最后int temp = 0; //臨時變量for (int j = 0; j < arr.length - 1; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("第一趟排序后的數組");System.out.println(Arrays.toString(arr));//第二趟排序,就是將第二大的數排在倒數第二位for (int j = 0; j < arr.length - 1 - 1; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("第二趟排序后的數組");System.out.println(Arrays.toString(arr));}第二次排序后得到得最終結果為:3, 2, 4, 6, 5, 10, 11 以此類推下面我們直接進行六次排序看看最終的結果是否與我們預期的一致。
public static void main(String[] args) {int arr[] = {3, 6, 4, 2, 11, 10, 5};//為了容易理解,我們把冒泡排序的演變過程,給大家展示一下。//第一趟排序,就是將最大的數排在最后int temp = 0; //臨時變量for (int j = 0; j < arr.length - 1; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("第一趟排序后的數組");System.out.println(Arrays.toString(arr));//第二趟排序,就是將第二大的數排在倒數第二位for (int j = 0; j < arr.length - 1 - 1; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("第二趟排序后的數組");System.out.println(Arrays.toString(arr));//第二趟排序,就是將第三大的數排在倒數第三位for (int j = 0; j < arr.length - 1 - 2; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("第三趟排序后的數組");System.out.println(Arrays.toString(arr));//第二趟排序,就是將第四大的數排在倒數第四位for (int j = 0; j < arr.length - 1 - 3; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("第四趟排序后的數組");System.out.println(Arrays.toString(arr));//第二趟排序,就是將第五大的數排在倒數第五位for (int j = 0; j < arr.length - 1 - 4; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("第五趟排序后的數組");System.out.println(Arrays.toString(arr));//第二趟排序,就是將最小的數排在第一位for (int j = 0; j < arr.length - 1 - 5; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j+1] = temp;}}System.out.println("最后一趟排序后的數組");System.out.println(Arrays.toString(arr));}不知道大家看完六次排序的代碼發現什么規律沒有,分開寫只是方便大家理解實際過程中只需要一個雙重循環就可以解決代碼冗余的問題。
public static void main(String[] args) {int arr[] = {3, 6, 4, 2, 11, 10, 5};int temp = 0; //臨時變量for (int i=0; i< arr.length -1; i++) {for (int j = 0; j < arr.length - 1 -i; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}System.out.println("第"+(i+1)+"趟排序后的數組");System.out.println(Arrays.toString(arr));}}當進行六次排序后還有一位數還需不需要進行第七次排序了?答案是不需要,因為確定了六個數據的位置已經沒必要知道第七個數據的位置了。對比上圖,雖然我們最終的結果正確了,但是大家有么有發現在第三次排序之后已經成功了。后續的數據都是一樣的結果,那么針對這種情況怎么優化呢?后面會給大家講到!
排序優化
針對上面提出的情況怎么優化呢?因為排序的過程中,各元素不斷接近自已的位置,如果一趟比較下來沒有進行過交換,就說明序列有序,因此要在排序過程中設置一個標志flag判斷元素是否進行過交換。從而減少不必要的比較。話不多說直接上代碼!
public static void main(String[] args) {int arr[] = {3, 6, 4, 2, 11, 10, 5};System.out.println("排序前");System.out.println(Arrays.toString(arr));//測試冒泡排序bubbleSort(arr);System.out.println("排序后");System.out.println(Arrays.toString(arr));}public static void bubbleSort(int[] arr){boolean flag = false; //標識變量,表示是否進行過交換int temp = 0; //臨時變量for (int i=0; i< arr.length -1; i++) {for (int j = 0; j < arr.length - 1 -i; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {flag = true; //表示交換過temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}if (!flag){ //在一趟排序中,一次交換都沒有發生過break;}else {flag = false; //重置flag,進行下次判斷}}}優化后的代碼,在for循環的運行中沒有進行交換就會走到break退出代碼。
性能測試
冒泡排序的速度為O(n的二次方),假如我們給數據組加入80000條數據我們來測試一下冒泡排序的性能到底如何。
public static void main(String[] args) {// int arr[] = {3, 6, 4, 2, 11, 10, 5};int arr[] = new int[80000];for (int i = 0;i<arr.length;i++){arr[i] = (int) (Math.random() * 8000000); //生成一個0-8000000的數}Date date1 = new Date();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String date1Str = dateFormat.format(date1);System.out.println("排序前的時間為:"+date1Str);//測試冒泡排序bubbleSort(arr);Date date2 = new Date();String date2Str = dateFormat.format(date2);System.out.println("排序后的時間為:"+date2Str);}public static void bubbleSort(int[] arr){boolean flag = false; //標識變量,表示是否進行過交換int temp = 0; //臨時變量for (int i=0; i< arr.length -1; i++) {for (int j = 0; j < arr.length - 1 -i; j++) {//如果前面的數比后面的數大,則交換if (arr[j] > arr[j + 1]) {flag = true; //表示交換過temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}if (!flag){ //在一趟排序中,一次交換都沒有發生過break;}else {flag = false; //重置flag,進行下次判斷}}}
經過我們的多次執行,發現冒泡排序在處理八萬條數據的時間大概為十秒左右由此可見冒泡排序的性能并不高!
總結
以上是生活随笔為你收集整理的详解Java算法之冒泡排序(Bubble Sorting)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode 738 单调递增的数字
- 下一篇: JCJC错别字检测系统API接口使用文档