算法入門教程-冒泡排序

上節(jié)我們分別通過案例迷宮和八皇后親自體驗了遞歸回溯算法的思想,本節(jié)我們學習常見八大算法之一的冒泡排序算法,親自感受下冒泡算法的思想.

冒泡排序算法介紹

冒泡排序算法的思想來源于生活中的啟迪,冬天的時候我們在燒開水的時候,可以清晰的在壺底看到氣泡依次從底部上升,在上升的過程中氣泡是由小變大徐徐上升直至破滅,這就是冒泡的生活來源

知道了冒泡的來源,我們大概明白了它的思想:我們可以假設(shè)有一組待排序的數(shù)字,從前往后,依次比較相鄰元素的值,如果發(fā)現(xiàn)逆序的現(xiàn)象,則進行位置的交換,讓數(shù)字大的元素往后移動即可,重復該步驟即可,這就是冒泡排序算法的思想,我們用圖解的方式來看下冒泡的過程

冒泡圖解過程

  • 假設(shè)我們有一組如下圖的數(shù)字需要排序
冒泡排序原始數(shù)據(jù).png

具體的步驟如下圖:

  • 第一趟的過程:
冒泡排序第一趟過程.png
  • 代碼實現(xiàn):
//待排序的數(shù)字的數(shù)組
    int [] array = {3,9,-1,10,-2};
//定義一個臨時的變量來臨時保存我們交換的數(shù)
    int temp = 0;
    for(int i = 0; i < array.length -1 ; i++) {
        //如果前面的數(shù)大于后面的,則進行交換
        if (array[i] > array[i+1]){
            temp = array[i];
            array[i] = array[i + 1];
            array[i + 1] = temp;
        }
    }
    System.out.println("第一趟排序的結(jié)果為:");
    System.out.println(Arrays.toString(array));
  • 測試結(jié)果如下圖:


    第一趟排序的最終結(jié)果圖.png

結(jié)合圖以及代碼實現(xiàn),更加生動形象的理解冒泡第一趟排序的過程,說白了就是相鄰數(shù)之間的比較然后進行位置的交換,通過這樣的比較找出最大的一個數(shù),有圖和測試結(jié)果圖發(fā)現(xiàn)第一趟的最大值為10且已經(jīng)放置在最后的位置處,接著看:

  • 第二趟:


    冒泡排序第二趟排序圖.png
  • 代碼實現(xiàn):

 // 第二趟排序,我們找出第二個大的數(shù),并放置在倒數(shù)第二個位置上
    for (int i = 0; i < array.length -1-1 ; i++) {
        //如果前面的數(shù)大于后面的,則進行交換
        if (array[i] > array[i+1]){
            temp = array[i];
            array[i] = array[i + 1];
            array[i + 1] = temp;
        }
    }
    System.out.println("第二趟排序的結(jié)果為:");
    System.out.println(Arrays.toString(array));
  • 測試結(jié)果圖:
第二趟測試結(jié)果圖.png

通過第二趟的排序我們找到了9是最大的數(shù)字并放置在倒數(shù)第二的位置上,我們接著看:

  • 第三趟排序的結(jié)果:
第三趟的排序圖.png
  • 代碼實現(xiàn):
    // 第三趟排序,我們找出第三個大的數(shù),并放置在倒數(shù)第三個位置上
    for (int i = 0; i < array.length -1-1-1 ; i++) {
        //如果前面的數(shù)大于后面的,則進行交換
        if (array[i] > array[i+1]){
            temp = array[i];
            array[i] = array[i + 1];
            array[i + 1] = temp;
        }
    }
    System.out.println("第三趟排序的結(jié)果為:");
    System.out.println(Arrays.toString(array));

-測試結(jié)果圖如下:


第三趟測試結(jié)果圖.png

通過第三趟的排序我們將3放置在了它應有的位置處,我們接著看:

  • 第四趟排序過程圖:
第四趟排序過程圖.png
  • 代碼實現(xiàn):
// 第四趟排序,我們找出第四個大的數(shù),并放置在倒數(shù)第四個位置上
    for (int i = 0; i < array.length -1-1-1-1 ; i++) {
        //如果前面的數(shù)大于后面的,則進行交換
        if (array[i] > array[i+1]){
            temp = array[i];
            array[i] = array[i + 1];
            array[i + 1] = temp;
        }
    }
    System.out.println("第四趟排序的結(jié)果為:");
    System.out.println(Arrays.toString(array));
  • 測試結(jié)果圖如下:
第四趟排序結(jié)果圖.png

經(jīng)過四次的排序,我們終于將該組數(shù)據(jù)排序完成,同時我們也可能找到了一些規(guī)律:

冒泡排序圖解規(guī)律總結(jié)
  • 我們會發(fā)現(xiàn)一共進行數(shù)組的大小-1的大的循環(huán)
  • 每一趟排序的次數(shù)都在減少

我們在上述的代碼中可以發(fā)現(xiàn),每一趟的for循環(huán)是重復的,因此我們可以將代碼進行整合優(yōu)化,一般封裝成一個方法即可,具體代碼如下:

//將冒泡排序封裝成一個方法
public static void bubbleSort(int[] array) {
    int temp = 0;
    for (int i = 0; i < array.length - 1; i++) {
        for (int j = 0; j < array.length - 1 - i; j++) {
            //如果前面的數(shù)大于后面的,則進行交換
            if (array[j] > array[j + 1]) {
                temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }

}

經(jīng)過封裝的話,我們直接調(diào)用該方法即可,只需要傳入需要排序的數(shù)組即可,其實我們上述的代碼還需要優(yōu)化,假如我們需要排序的數(shù)組為:int [] array = {3,9,-1,10,20};我們來測試一把,結(jié)果如下圖:

測試結(jié)果圖.png

在上圖的測試結(jié)果中我們看到的是,同樣也進行了四次的排序,其實在第三趟的排序過后就已經(jīng)完成了排序,第四次就不應該在排序,影響我們代碼的執(zhí)行效率,所以這里是需要優(yōu)化的一個點,具體優(yōu)化代碼如下:

代碼優(yōu)化
//將冒泡排序封裝成一個方法
public static void bubbleSort(int[] array) {
    int temp = 0;
    //定義一個標識,標識是否進行交換過
    boolean flag = false;
    for (int i = 0; i < array.length - 1; i++) {
        for (int j = 0; j < array.length - 1 - i; j++) {
            //如果前面的數(shù)大于后面的,則進行交換
            if (array[j] > array[j + 1]) {
                flag = true;
                temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
        System.out.println("第" + (i + 1) + "趟排序的結(jié)果為:");
        System.out.println(Arrays.toString(array));

        if (!flag) { //表示在一趟排序中沒有進行過一次交換
            break;
        } else {
            flag = false; //置為false,進行下次判斷
        }
    }
}

我們通過定義一個標識flag來控制我們的代碼,這也是算法中常見的做法,直接來看測試結(jié)果:

優(yōu)化后的測試結(jié)果.png

測試結(jié)果證明我們的代碼是沒有問題的,這也是我們代碼的一個小小的優(yōu)化,對于一個算法我們一般很關(guān)心算法的執(zhí)行時間,那么涉及到了一個知識點時間頻度和時間復雜度的問題,關(guān)于這個知識點,后續(xù)有時間的話來專門寫一篇文章細說,這里就不多說了,我們最后來測一下冒泡排序的執(zhí)行時間,修改了一下要排序的數(shù)組,直接看代碼:

冒泡排序的執(zhí)行時間的測試
  • 代碼
  //冒泡排序的時間復雜度測試
    int [] arr = new int[100000];
    for (int i = 0; i < arr.length; i++) {
        arr[i] = (int)(Math.random() * 100000); //隨機生成[0,80000)的數(shù)
    }

    Date date1 = new Date();
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String format = dateFormat.format(date1);
    System.out.println("排序前的時間為:"+format);
    //進行排序
    bubbleSort(arr);
    Date date2 = new Date();
    SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String format2 = dateFormat.format(date2);
    System.out.println("排序后的時間為:"+format2);
  • 測試結(jié)果圖:
執(zhí)行時間測試結(jié)果圖.png

我們可以看到的是,當排序10w的數(shù)據(jù)時,需要20多秒,也不一定,多執(zhí)行幾次對比下,其實關(guān)于冒泡排序算法的時間復雜度為O(n^2),至于為啥是這個值,因為我們是兩個for循環(huán)來執(zhí)行的,那么關(guān)于冒泡排序算法的學習就到這里了.....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖荆虱,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件墅诡,死亡現(xiàn)場離奇詭異搜骡,居然都是意外死亡蚌卤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門幽钢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歉备,“玉大人,你說我怎么就攤上這事搅吁⊥矗” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵谎懦,是天一觀的道長肚豺。 經(jīng)常有香客問我,道長界拦,這世上最難降的妖魔是什么吸申? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮享甸,結(jié)果婚禮上截碴,老公的妹妹穿的比我還像新娘。我一直安慰自己蛉威,他們只是感情好日丹,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚯嫌,像睡著了一般哲虾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上择示,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天束凑,我揣著相機與錄音,去河邊找鬼栅盲。 笑死汪诉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的谈秫。 我是一名探鬼主播扒寄,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拟烫!你這毒婦竟也來了旗们?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤构灸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喜颁,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡稠氮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了半开。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隔披。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖寂拆,靈堂內(nèi)的尸體忽然破棺而出奢米,到底是詐尸還是另有隱情,我是刑警寧澤纠永,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布鬓长,位于F島的核電站,受9級特大地震影響尝江,放射性物質(zhì)發(fā)生泄漏涉波。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一炭序、第九天 我趴在偏房一處隱蔽的房頂上張望啤覆。 院中可真熱鬧,春花似錦惭聂、人聲如沸窗声。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽笨觅。三九已至,卻和暖如春侨歉,著一層夾襖步出監(jiān)牢的瞬間屋摇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工幽邓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留炮温,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓牵舵,卻偏偏與公主長得像柒啤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子畸颅,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355