排序算法總結(1):冒泡排序

2021-02-25 算法與數據結構

冒泡排序是一種交換排序

什麼是交換排序呢?

交換排序:兩兩比較待排序的關鍵字,並交換不滿足次序要求的那對數,直到整個表都滿足次序要求為止。

算法思想

它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。

這個算法的名字由來是因為越小的元素會經由交換慢慢「浮」到數列的頂端,故名。

假設有一個大小為 N 的無序序列。冒泡排序就是要每趟排序過程中通過兩兩比較,找到第 i 個小(大)的元素,將其往上排。

圖-冒泡排序示例圖

以上圖為例,演示一下冒泡排序的實際流程:

假設有一個無序序列  { 4. 3. 1. 2, 5 }

第一趟排序:通過兩兩比較,找到第一小的數值 1 ,將其放在序列的第一位。

第二趟排序:通過兩兩比較,找到第二小的數值 2 ,將其放在序列的第二位。

第三趟排序:通過兩兩比較,找到第三小的數值 3 ,將其放在序列的第三位。

至此,所有元素已經有序,排序結束。

要將以上流程轉化為代碼,我們需要像機器一樣去思考,不然編譯器可看不懂。

假設要對一個大小為 N 的無序序列進行升序排序(即從小到大)。

(1) 每趟排序過程中需要通過比較找到第 i 個小的元素。

所以,我們需要一個外部循環,從數組首端(下標 0) 開始,一直掃描到倒數第二個元素(即下標 N - 2) ,剩下最後一個元素,必然為最大。

(2) 假設是第 i 趟排序,可知,前 i-1 個元素已經有序。現在要找第 i 個元素,只需從數組末端開始,掃描到第 i 個元素,將它們兩兩比較即可。

所以,需要一個內部循環,從數組末端開始(下標 N - 1),掃描到 (下標 i + 1)。

核心代碼

public void bubbleSort(int[] list) {
    int temp = 0; 

    
    for (int i = 0; i < list.length - 1; i++) {
        
        for (int j = list.length - 1; j > i; j--) {
            
            if (list[j - 1] > list[j]) {
                temp = list[j - 1];
                list[j - 1] = list[j];
                list[j] = temp;
            }
        }

        System.out.format("第 %d 趟: ", i);
        printAll(list);
    }
}

冒泡排序算法的性能

時間複雜度

若文件的初始狀態是正序的,一趟掃描即可完成排序。所需的關鍵字比較次數C和記錄移動次數M均達到最小值:Cmin = N - 1, Mmin = 0。所以,冒泡排序最好時間複雜度為O(N)。

若初始文件是反序的,需要進行 N -1 趟排序。每趟排序要進行 N - i 次關鍵字的比較(1 ≤ i ≤ N - 1),且每次比較都必須移動記錄三次來達到交換記錄位置。在這種情況下,比較和移動次數均達到最大值:

Cmax = N(N-1)/2 = O(N2)
Mmax = 3N(N-1)/2 = O(N2)
冒泡排序的最壞時間複雜度為O(N2)。
因此,冒泡排序的平均時間複雜度為O(N2)。

總結起來,其實就是一句話:當數據越接近正序時,冒泡排序性能越好。

算法穩定性

冒泡排序就是把小的元素往前調或者把大的元素往後調。比較是相鄰的兩個元素比較,交換也發生在這兩個元素之間。

所以相同元素的前後順序並沒有改變,所以冒泡排序是一種穩定排序算法。

對冒泡排序常見的改進方法是加入標誌性變量exchange,用於標誌某一趟排序過程中是否有數據交換。

如果進行某一趟排序時並沒有進行數據交換,則說明所有數據已經有序,可立即結束排序,避免不必要的比較過程。

核心代碼


public void bubbleSort_2(int[] list) {
    int temp = 0; 
    boolean bChange = false; 

    
    for (int i = 0; i < list.length - 1; i++) {
        bChange = false;
        
        for (int j = list.length - 1; j > i; j--) {
            
            if (list[j - 1] > list[j]) {
                temp = list[j - 1];
                list[j - 1] = list[j];
                list[j] = temp;
                bChange = true;
            }
        }

        
        if (false == bChange)
            break;

        System.out.format("第 %d 趟: ", i);
        printAll(list);
    }
}

代碼實現

 1 package notes.javase.algorithm.sort;
 2  
 3 import java.util.Random;
 4  
 5 public class BubbleSort {
 6  
 7     public void bubbleSort(int[] list) {
 8         int temp = 0; 
 9  
10         
11         for (int i = 0; i < list.length - 1; i++) {
12             
13             for (int j = list.length - 1; j > i; j--) {
14                 
15                 if (list[j - 1] > list[j]) {
16                     temp = list[j - 1];
17                     list[j - 1] = list[j];
18                     list[j] = temp;
19                 }
20             }
21  
22             System.out.format("第 %d 趟: ", i);
23             printAll(list);
24         }
25     }
26  
27     
28     public void bubbleSort_2(int[] list) {
29         int temp = 0; 
30         boolean bChange = false; 
31  
32         
33         for (int i = 0; i < list.length - 1; i++) {
34             bChange = false;
35             
36             for (int j = list.length - 1; j > i; j--) {
37                 
38                 if (list[j - 1] > list[j]) {
39                     temp = list[j - 1];
40                     list[j - 1] = list[j];
41                     list[j] = temp;
42                     bChange = true;
43                 }
44             }
45  
46             
47             if (false == bChange)
48                 break;
49  
50             System.out.format("第 %d 趟: ", i);
51             printAll(list);
52         }
53     }
54  
55     
56     public void printAll(int[] list) {
57         for (int value : list) {
58             System.out.print(value + " ");
59         }
60         System.out.println();
61     }
62  
63     public static void main(String[] args) {
64         
65         final int MAX_SIZE = 10;
66         int[] array = new int[MAX_SIZE];
67         Random random = new Random();
68         for (int i = 0; i < MAX_SIZE; i++) {
69             array[i] = random.nextInt(MAX_SIZE);
70         }
71  
72         
73         BubbleSort bubble = new BubbleSort();
74         System.out.print("排序前: ");
75         bubble.printAll(array);
76         
77         bubble.bubbleSort_2(array);
78         System.out.print("排序後: ");
79         bubble.printAll(array);
80     }
81 }

運行結果

排序前:    2    9    9    7    1    9    0    2    6    8  
第 0 趟:    0    2    9    9    7    1    9    2    6    8  
第 1 趟:    0    1    2    9    9    7    2    9    6    8  
第 2 趟:    0    1    2    2    9    9    7    6    9    8  
第 3 趟:    0    1    2    2    6    9    9    7    8    9  
第 4 趟:    0    1    2    2    6    7    9    9    8    9  
第 5 趟:    0    1    2    2    6    7    8    9    9    9  
排序後:    0    1    2    2    6    7    8    9    9    9  

相關焦點

  • Java實現冒泡排序算法
    從這一篇開始,我們把每一種排序算法,從算法的思想,到代碼實現都做一個分享。那麼你準備好了嗎?我們這一篇的主角是:冒泡排序#考考你:1.你知道冒泡排序的核心思想嗎?2.你能用java實現冒泡排序嗎?3.你能寫出更優秀的冒泡排序代碼嗎?
  • 重溫7種排序算法 第一篇,交換排序算法:冒泡排序、快速排序
    排序算法可分為以下幾類:    交換排序算法:冒泡排序、快速排序;    選擇排序算法:簡單選擇排序、堆排序;    插入排序算法:直接插入排序、希爾排序;    歸併排序算法。    主要做了以上7種排序算法的筆記,字數可能較多,所以分為幾篇。
  • 冒泡排序算法的來龍去脈
    1 簡介每次比較相鄰的元素,如果它們的順序錯誤就把它們交換過來。956年就有人開始研究冒泡排序,之後有很多人嘗試對其進行改進,但是結果令人失望。1974年圖靈獎獲得者Donald E.Knuth說:「冒泡排序除了它迷人的名字和導致了某些有趣的理論問題這一事實之外,似乎沒有什麼值得推薦的。」2 算法描述其基本思想是每次比較兩個相鄰的元素,如果它們順序錯誤就把它們交換過來。例如需要將12、35、99、18、76這5個數字從大到小順序排列。1>首先比較第1位和第2位大小,12比35要小,進行交換。
  • Python中的冒泡排序算法,冒泡排序的優缺點,中級python技術點
    Python中的冒泡排序算法冒泡排序是最直接的排序算法之一。它的名字來自於算法的工作方式:每經過一個新遍歷,列表中最大的元素就會向正確的位置「冒泡」。冒泡排序包括對列表進行多次遍歷、逐個比較元素以及交換順序混亂的相鄰項。
  • 輕鬆搞定Java冒泡排序算法以及算法優化
    作為Java程式設計師,簡單的算法,必須要掌握的。尤其初級開發人員在面試過程或者筆試都會有相應算法題,今天我們講解冒泡排序算法是如何實現的以及優化方法。缺點:時間複雜度太高、效率比較慢、一輪比較都需要換位置,所以效率不高,假如現在一個數組裡面有N個數,那麼排序完成需要比較N*(N-1)/2次。
  • 排序算法之冒泡排序及其優化
    冒泡排序思想比較相鄰兩個元素,如果前面的元素比後面的元素大,則交換位置。最後一個元素必定會是最大值。排除掉最後一位元素,繼續循環,直至沒有元素需要比較可以看出,冒牌排序其實和選擇排序時很像的,只不過選擇排序是比較數據,先記錄下最小/大值的下標,等一趟循環結束的時候再交換位置;而冒泡排序在比較數據的同時也做了交換。性能時間複雜度與選擇排序一樣,時間複雜度為O(n^2)。
  • JS家的排序算法 十大經典算法排序總結
    它是一本很好的針對前端開發者們的入門算法書籍,可是,它有一個很大的缺陷,就是裡面有很多明顯的小錯誤,明顯到就連我這種半路出家的程序猿都能一眼看出來。還有一個問題是,很多重要的算法和數據結構知識並沒有在這本書裡被提到。這些問題對於作為一個晚期強迫症患者的我來說簡直不能忍。於是乎,一言不合我就決定自己找資料總結算法。那麼,我就從算法領域裡最基礎的知識點——排序算法總結起好了。
  • Java中常見的排序算法有哪些?---冒泡排序
    排序相關的的基本概念排序: 將一組雜亂無章的數據按一定的規律順次排列起來。數據表( data list): 它是待排序數據對象的有限集合。排序碼(key):通常數據對象有多個屬性域,即多個數據成員組成,其中有一個屬性域可用來區分對象,作為排序依據。該域即為排序碼。
  • JavaScript算法之冒泡排序
    冒泡排序是討論最多的算法之一,它比較容易理解,但是效率較低。如果數組是已排序的,冒泡排序只需要遍歷一次數組,不過最壞的情況下運行時間為 O(n2),非常低效。儘管如此,理解這個算法依然很重要,需要明白它為什麼效率低下。本文將介紹實現冒泡排序的兩個思路。
  • 使用PHP完成冒泡排序算法
    原理本文使用的排序數組數據如下:$arr1 = array(18,22,12, 15,23,9);遍歷一個數組,在此過程中,將相鄰的兩個單元的值進行比較(倆倆相比,左邊比右邊大就對換位置):下方圖中所示為上面所列舉的算法過程:規律總結1.要進行從頭到尾兩兩比較並進行交換位置的趟數為$n-1趟,$n是總個數(數組長度)2.每次都對相鄰的兩個數據進行大小比較,如果需要,就交換他們的位置!
  • 單集合排序:冒泡排序法
    在日常開發中經常會遇到一類問題,就是對一個集合的數據進行排序掌握一些排序算法,對於日常開發是非常有幫助今天介紹一下冒泡排序法01算法邏輯>02時間複雜度由上圖邏輯可以得出,冒泡排序的循環次數為由循環次數可以得出,冒泡排序的時間複雜度為03空間複雜度由上圖邏輯可以得出
  • 力扣(LeetCode)- 常見的排序算法總結
    1. 如何分析一個排序算法好壞時間複雜度、比較和交換次數、原地排序(空間複雜度為(1))、排序穩定性(相等元素之間的位置先後順序不變)。選擇排序是不穩定排序,所以應用最少。2. 插入排序比冒泡排序哪個好?插入排序好。
  • 看動畫學算法之:排序-冒泡排序
    簡介排序可能是所有的算法中最最基礎和最最常用的了。排序是一個非常經典的問題,它以一定的順序對一個數組(或一個列表)中的項進行重新排序。排序算法有很多種,每個都有其自身的優點和局限性。今天我們來學習最最簡單的冒泡排序算法。冒泡排序的原理冒泡排序的原理很簡單,我們想像一下一個一個的氣泡上浮的過程。
  • 經典排序算法一 冒泡排序(JAVA實現)
    冒泡排序原理:相鄰的兩個元素進行比較,將值大的元素移動到右端。冒泡排序實現思路:遍歷要排序的元素,依次比較相鄰的兩個元素,值大的移動到右端,則第二次就可以忽略第一次遍歷放在最右端的元素,依次類推直到遍歷到n-1次只剩下2個元素進行比較,冒泡排序結束。
  • 你所知道的十大排序算法的總結(冒泡,選擇,插入,希爾,歸併,快排,堆...
    時間複雜度:一個算法執行需要耗費的時間;空間複雜度:運行這一個算法需要內存的大小。可以參考:javascript系列--時間複雜度和空間複雜度3、排序算法圖片總結解釋:n表示數據規模,k表示桶的個數,in-place表示佔用常數內存,out-place表示佔用額外內存。
  • 圖文詳解冒泡排序
    1. 基本概念1.1 算法原理冒泡排序就是從序列中的第一個元素開始,依次對相鄰的兩個元素進行比較,如果前一個元素大於後一個元素則交換它們的位置。如果前一個元素小於或等於後一個元素,則不交換它們;這一比較和交換的操作一直持續到最後一個還未排好序的元素為止。
  • 排序算法問題:穩定排序與不穩定排序
    作為在面試中經常被考到的考點,每一個程式設計師都應該知道,本文總結了常見算法的穩定性,值得一看,希望能對大家有所幫助。1、冒泡排序冒泡排序就是把小的元素往前調或者把大的元素往後調。比較是相鄰的兩個元素比較,交換也發生在這兩個元素之間。
  • JavaScript面經之冒泡排序
    文/大白老師圖/大白老師我們去大廠面試前端的時候,最容易被問及的一個內容就是排序,而其中,冒泡排序作為最基礎的排序算法,很多時候是被要求進行手寫代碼的,面試官通過對手寫代碼的考察,可以看出求職者的算法基礎功底、JavaScript語言功底以及在開發時,對變量的語義化水平
  • 坐在馬桶上看算法:鄰居好說話,冒泡排序
    即便只給你5個數進行排序(例如這5個數是1,1912345678,2100000000,18000000和912345678),你也仍然需要2100000001個「桶」,這真是太浪費了空間了!還有,如果現在需要排序的不再是整數而是一些小數,比如將5.56789,2.12,1.1,3.123,4.1234這五個數進行從小大排序又該怎麼辦呢?現在我們來學習另一種新的排序算法:冒泡排序。
  • 程式設計師必備的幾種常見排序算法和搜索算法總結
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫前言最近為了鞏固一下自己的算法基礎,又把算法書裡的基本算法刷了一遍, 特地總結一下前端工程師需要了解的排序算法和搜索算法知識,雖然還有很多高深算法需要了解