日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解冒泡排序

發(fā)布時間:2023/12/4 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解冒泡排序 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


轉(zhuǎn)自:靜默虛空

http://www.cnblogs.com/jingmoxukong/p/4302718.html


要點


冒泡排序是一種交換排序。


什么是交換排序呢?


交換排序:兩兩比較待排序的關(guān)鍵字,并交換不滿足次序要求的那對數(shù),直到整個表都滿足次序要求為止。


算法思想


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


這個算法的名字由來是因為越小的元素會經(jīng)由交換慢慢“浮”到數(shù)列的頂端,故名。


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




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


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


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


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


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


至此,所有元素已經(jīng)有序,排序結(jié)束。?


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


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


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


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


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


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


核心代碼


public?void?bubbleSort(int[]?list)?{

????int?temp?=?0;?// 用來交換的臨時數(shù)?

????// 要遍歷的次數(shù)

????for?(int?i?=?0;?i?<?list.length?-?1;?i++)?{

????????// 從后向前依次的比較相鄰兩個數(shù)的大小,遍歷一次后,把數(shù)組中第i小的數(shù)放在第i個位置上

????????for?(int?j?=?list.length?-?1;?j?>?i;?j--)?{

????????????// 比較相鄰的元素,如果前面的數(shù)大于后面的數(shù),則交換

????????????if?(list[j?-?1]?>?list[j])?{

????????????????temp?=?list[j?-?1];?

????????????????list[j?-?1]?=?list[j];

????????????????list[j]?=?temp;?

????????????}

????????}

????????System.out.format("第 %d 趟:\t",?i);

????????printAll(list);

????}?

}


冒泡排序算法的性能



時間復雜度


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


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


Cmax = N(N-1)/2 = O(N2)

Mmax = 3N(N-1)/2 = O(N2)


冒泡排序的最壞時間復雜度為O(N2)。

因此,冒泡排序的平均時間復雜度為O(N2)。


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


算法穩(wěn)定性


冒泡排序就是把小的元素往前調(diào)或者把大的元素往后調(diào)。比較是相鄰的兩個元素比較,交換也發(fā)生在這兩個元素之間。


所以相同元素的前后順序并沒有改變,所以冒泡排序是一種穩(wěn)定排序算法。


優(yōu)化


對冒泡排序常見的改進方法是加入標志性變量exchange,用于標志某一趟排序過程中是否有數(shù)據(jù)交換。


如果進行某一趟排序時并沒有進行數(shù)據(jù)交換,則說明所有數(shù)據(jù)已經(jīng)有序,可立即結(jié)束排序,避免不必要的比較過程。


核心代碼


// 對 bubbleSort 的優(yōu)化算法

public?void?bubbleSort_2(int[]?list)?{

????int?temp?=?0;?// 用來交換的臨時數(shù)

????boolean?bChange?=?false;?// 交換標志

????// 要遍歷的次數(shù)

????for?(int?i?=?0;?i?<?list.length?-?1;?i++)?{

????????bChange?=?false;

????????// 從后向前依次的比較相鄰兩個數(shù)的大小,遍歷一次后,把數(shù)組中第i小的數(shù)放在第i個位置上

????????for?(int?j?=?list.length?-?1;?j?>?i;?j--)?{

????????????// 比較相鄰的元素,如果前面的數(shù)大于后面的數(shù),則交換

????????????if?(list[j?-?1]?>?list[j])?{

????????????????temp?=?list[j?-?1];

????????????????list[j?-?1]?=?list[j];

????????????????list[j]?=?temp;

????????????????bChange?=?true;

????????????}

????????}

????????// 如果標志為false,說明本輪遍歷沒有交換,已經(jīng)是有序數(shù)列,可以結(jié)束排序

????????if?(false?==?bChange)?

????????????break;?

????????System.out.format("第 %d 趟:\t",?i);

????????printAll(list);

????}

}


完整參考代碼


package?notes.javase.algorithm.sort;

import?java.util.Random;

public?class?BubbleSort?{

????public?void?bubbleSort(int[]?list)?{

????????int?temp?=?0;?// 用來交換的臨時數(shù)

????????// 要遍歷的次數(shù)

????????for?(int?i?=?0;?i?<?list.length?-?1;?i++)?{

????????????// 從后向前依次的比較相鄰兩個數(shù)的大小,遍歷一次后,把數(shù)組中第i小的數(shù)放在第i個位置上

????????????for?(int?j?=?list.length?-?1;?j?>?i;?j--)?{

????????????????// 比較相鄰的元素,如果前面的數(shù)大于后面的數(shù),則交換

????????????????if?(list[j?-?1]?>?list[j])?{

????????????????????temp?=?list[j?-?1];

????????????????????list[j?-?1]?=?list[j];

????????????????????list[j]?=?temp;

????????????????}

????????????}

????????????System.out.format("第 %d 趟:\t",?i);

????????????printAll(list);

????????}

????}

????// 對 bubbleSort 的優(yōu)化算法

????public?void?bubbleSort_2(int[]?list)?{

????????int?temp?=?0;?// 用來交換的臨時數(shù)

????????boolean?bChange?=?false;?// 交換標志

????????// 要遍歷的次數(shù)

????????for?(int?i?=?0;?i?<?list.length?-?1;?i++)?{

????????????bChange?=?false;

????????????// 從后向前依次的比較相鄰兩個數(shù)的大小,遍歷一次后,把數(shù)組中第i小的數(shù)放在第i個位置上

????????????for?(int?j?=?list.length?-?1;?j?>?i;?j--)?{

????????????????// 比較相鄰的元素,如果前面的數(shù)大于后面的數(shù),則交換

????????????????if?(list[j?-?1]?>?list[j])?{

????????????????????temp?=?list[j?-?1];

????????????????????list[j?-?1]?=?list[j];

????????????????????list[j]?=?temp;

????????????????????bChange?=?true;

????????????????}

????????????}

????????????// 如果標志為false,說明本輪遍歷沒有交換,已經(jīng)是有序數(shù)列,可以結(jié)束排序

????????????if?(false?==?bChange)

????????????????break;

????????????System.out.format("第 %d 趟:\t",?i);

????????????printAll(list);

????????}

????}

????// 打印完整序列

????public?void?printAll(int[]?list)?{

????????for?(int?value?:?list)?{

????????????System.out.print(value?+?"\t");

????????}

????????System.out.println();

????}

????public?static?void?main(String[]?args)?{

????????// 初始化一個隨機序列

????????final?int?MAX_SIZE?=?10;

????????int[]?array?=?new?int[MAX_SIZE];

????????Random?random?=?new?Random();

????????for?(int?i?=?0;?i?<?MAX_SIZE;?i++)?{

????????????array[i]?=?random.nextInt(MAX_SIZE);

????????}

????????// 調(diào)用冒泡排序方法

????????BubbleSort?bubble?=?new?BubbleSort();

????????System.out.print("排序前:\t");

????????bubble.printAll(array);

????????// bubble.bubbleSort(array);

????????bubble.bubbleSort_2(array);

????????System.out.print("排序后:\t");

????????bubble.printAll(array);

????}

}


運行結(jié)果



參考資料


《數(shù)據(jù)結(jié)構(gòu)習題與解析》(B級第3版)


創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的详解冒泡排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。