排序算法圖解之Java冒泡排序及優(yōu)化
1.冒泡排序簡(jiǎn)介
冒泡排序(Bubble Sorting)即:通過(guò)對(duì)待排序的序列從前往后,依次比較相鄰元素的值,若發(fā)現(xiàn)逆序則交換位置,使較大的元素逐漸移動(dòng)到后部,就像水底的氣泡一樣逐漸從水面冒出來(lái),這就是冒泡名稱的由來(lái)
2.圖解算法
以將序列{3, 9, -1, 10, -20}從小到大排序?yàn)槔?/strong>
基本思想就是,在每一趟排序?qū)崿F(xiàn)將最大的數(shù)移到序列的最后端!這主要通過(guò)比較相鄰兩個(gè)元素實(shí)現(xiàn),當(dāng)相鄰的兩個(gè)元素逆序的時(shí)候,我們就交換它們。
第1趟排序:
第1趟排序共比較了4次,將最大的數(shù)10冒泡到了序列的尾部。
第2趟排序:
由于第一趟排序已經(jīng)將最大是數(shù)10給冒泡到了最末端,因此在本次排序中,不需要再比較最后一個(gè)元素,故共比較了3次,將子序列(前四個(gè)元素)中最大的數(shù)9(整個(gè)序列中倒數(shù)第二大的數(shù))冒泡到了子序列的尾端(原序列的倒數(shù)第二個(gè)位置)。
第3趟排序:
在第三趟排序時(shí),同理,倒數(shù)兩個(gè)元素位置已經(jīng)確定,即第一、第二大的數(shù)已經(jīng)排好位置,只需要再將倒數(shù)第三大的數(shù)確認(rèn)即可。故比較2次,實(shí)現(xiàn)倒數(shù)第三大的數(shù)3的位置確定。
第4趟排序:
在第四趟排序時(shí),只有第一、第二個(gè)元素的位置還不確定,只需要比較一次,若逆序,則交換即可。到此,排序算法完成,原序列已經(jīng)排序成為一個(gè)遞增的序列!
小結(jié)
一共進(jìn)行了數(shù)組大小-1次趟排序,即外層循環(huán)arr.length-1次;每趟排序進(jìn)行了逐趟減小次數(shù)的比較,即內(nèi)層循環(huán)arr.length-i-1次,i從0依次增加。
3.冒泡排序代碼實(shí)現(xiàn)
參考代碼如下,為了便于觀察結(jié)果,在循環(huán)中添加了相應(yīng)的輸出語(yǔ)句:
import java.util.Arrays; /** * @author 興趣使然黃小黃 * @version 1.0 * 冒泡排序 */ public class BubbleSort { public static void main(String[] args) { int[] array = {3, 9, -1, 10, -20}; //排序前 System.out.println("排序前:" + Arrays.toString(array)); //冒泡排序 for (int i = 0; i < array.length - 1; i++) { System.out.println("第" + (i+1) + "趟排序開始!"); for (int j = 0; j < array.length - i - 1; j++) { //如果前面的數(shù)比后面的數(shù)大,則交換 if(array[j] > array[j+1]){ //交換 int temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } System.out.println("------第" + (j+1) + "趟排序: " + Arrays.toString(array)); } System.out.println("第" + (i+1) + "趟排序完成: " + Arrays.toString(array)); System.out.println("================================================"); } //輸出排序后的結(jié)果 System.out.println("排序后:" + Arrays.toString(array)); } }
實(shí)現(xiàn)結(jié)果:
4.冒泡排序算法的優(yōu)化
舉個(gè)例子,將待排序的序列改為:{5,1,2,3,4},用以上算法來(lái)處理,觀察一下結(jié)果:
可以發(fā)現(xiàn),當(dāng)?shù)谝惶伺判蚪Y(jié)束的時(shí)候,序列已經(jīng)排序完成: 即將5冒泡到了最后,序列實(shí)現(xiàn)了從小到大排序。但是原冒泡排序算法,還是義無(wú)反顧的進(jìn)行了數(shù)組大小-1趟排序(我可真是大冤種?。?/strong>
因此,我們需要嘗試對(duì)算法進(jìn)行優(yōu)化!
發(fā)現(xiàn):在冒泡排序的過(guò)程中,各個(gè)元素都在不斷的接近自己的位置,如果下一趟比較中沒有進(jìn)行過(guò)任何交換,則說(shuō)明序列已經(jīng)有序, 則排序算法已經(jīng)可以返回結(jié)果。因此,考慮在排序算法過(guò)程中添加一個(gè)標(biāo)志flag判斷元素是否進(jìn)行過(guò)交換,以減少不必要的冤種行為!
優(yōu)化代碼如下:
import java.util.Arrays; /** * @author 興趣使然黃小黃 * @version 1.0 * 冒泡排序優(yōu)化 */ public class BubbleSort { public static void main(String[] args) { int[] array = {5, 1, 2, 3, 4}; //排序前 System.out.println("排序前:" + Arrays.toString(array)); boolean flag = false; //用于標(biāo)記是否進(jìn)行了交換,true則說(shuō)明進(jìn)行了交換,false表示無(wú) //冒泡排序 for (int i = 0; i < array.length - 1; i++) { System.out.println("第" + (i+1) + "趟排序開始!"); for (int j = 0; j < array.length - i - 1; j++) { //如果前面的數(shù)比后面的數(shù)大,則交換 if(array[j] > array[j+1]){ //交換 flag = true; //標(biāo)記進(jìn)行了交換 int temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } System.out.println("------第" + (j+1) + "趟排序: " + Arrays.toString(array)); } System.out.println("第" + (i+1) + "趟排序完成: " + Arrays.toString(array)); System.out.println("================================================"); if (!flag){ //如果沒有進(jìn)行交換則直接退出,說(shuō)明排序已經(jīng)完成 break; }else { //回退 flag = false; } } //輸出排序后的結(jié)果 System.out.println("排序后:" + Arrays.toString(array)); } }
四趟排序,優(yōu)化成了只需要兩趟排序!又是一個(gè)不可多得的小技巧!在算法程序題中,flag的設(shè)置是一種常用的編程思想,常常用于回溯算法中,小伙伴們要學(xué)會(huì)舉一反三~
到此這篇關(guān)于排序算法圖解之Java冒泡排序及優(yōu)化的文章就介紹到這了,更多相關(guān)Java冒泡排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實(shí)現(xiàn)前端驗(yàn)證碼圖片生成和校驗(yàn)
這篇文章主要為大家詳細(xì)介紹了SpringBoot實(shí)現(xiàn)前端驗(yàn)證碼圖片生成和校驗(yàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02出現(xiàn)SLF4J:?Failed?to?load?class?“org.slf4j.impl.StaticLog
本文主要介紹了出現(xiàn)SLF4J:?Failed?to?load?class?“org.slf4j.impl.StaticLoggerBinder“.的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07基于Spring p標(biāo)簽和c標(biāo)簽注入方式
這篇文章主要介紹了Spring p標(biāo)簽和c標(biāo)簽注入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09SpringSecurity+JWT實(shí)現(xiàn)前后端分離的使用詳解
這篇文章主要介紹了SpringSecurity+JWT實(shí)現(xiàn)前后端分離的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Eclipse 項(xiàng)目出現(xiàn)錯(cuò)誤(紅色嘆號(hào))解決方法
這篇文章主要介紹了Eclipse 項(xiàng)目出現(xiàn)錯(cuò)誤(紅色嘆號(hào))解決方法的相關(guān)資料,需要的朋友可以參考下2017-06-06SSH框架網(wǎng)上商城項(xiàng)目第3戰(zhàn)之使用EasyUI搭建后臺(tái)頁(yè)面框架
SSH框架網(wǎng)上商城項(xiàng)目第3戰(zhàn)之使用EasyUI搭建后臺(tái)頁(yè)面框架,討論兩種搭建方式:基于frameset和基于easyUI,感興趣的小伙伴們可以參考一下2016-05-05Java并發(fā)編程中的synchronized關(guān)鍵字詳細(xì)解讀
這篇文章主要介紹了Java并發(fā)編程中的synchronized關(guān)鍵字詳細(xì)解讀,在Java早期版本中,synchronized 屬于 重量級(jí)鎖,效率低下,這是因?yàn)楸O(jiān)視器鎖(monitor)是依賴于底層的操作系統(tǒng)的Mutex Lock來(lái)實(shí)現(xiàn)的,Java 的線程是映射到操作系統(tǒng)的原生線程之上的,需要的朋友可以參考下2023-12-12java文件復(fù)制代碼片斷(java實(shí)現(xiàn)文件拷貝)
本文介紹java實(shí)現(xiàn)文件拷貝的代碼片斷,大家可以直接放到程序里運(yùn)行2014-01-01