java版十大排序經(jīng)典算法:完整代碼
十大排序算法對比
關(guān)于最后一列的穩(wěn)定性,我稍微解釋下,例如對序列:1 2 4 2 6 排序,序列中存在兩個2,如果我們把這兩個2標(biāo)記上(讓他倆不同),排序之后,前面的2還在前面,那么就稱這種排序是穩(wěn)定的,反之不穩(wěn)定。
冒泡排序
簡單解釋: 原理就如算法名字一樣,就像水中的氣泡一樣,每次我都把最大的或最小的放到最后面,這樣總共需要n-1趟即可完成排序,這就是第一層循環(huán),第二次循環(huán)就是遍歷未被固定的那些數(shù)(理解成數(shù)組左邊的數(shù),因?yàn)槊繉友h(huán)都會把最大或最小的數(shù)升到最右邊固定起來,下次就不遍歷這些數(shù)了),兩層循環(huán)遍歷結(jié)束后,所有的數(shù)就排好序了。 兩層循環(huán)所以冒泡排序算法的時間復(fù)雜度是O( n 2 n^{2} n2),是一個非常高的時間復(fù)雜度,我在下面的代碼進(jìn)行了優(yōu)化,加了一個標(biāo)志位,如果上一次循環(huán)未發(fā)生交換,就說明已經(jīng)是有序的了,就不繼續(xù)下去了,反之繼續(xù)進(jìn)行下一輪。
完整代碼:
package com.keafmd.Sequence; /** * Keafmd * * @ClassName: BubbleSort * @Description: 冒泡排序 * @author: 牛哄哄的柯南 * @date: 2021-06-24 10:31 */ public class BubbleSort { //冒泡排序 public static void bubbleSort(int[] arr, boolean ascending) { //exchange標(biāo)志表示為升序排序還是降序排序 boolean flag = true; //加一個標(biāo)志位,記錄上一次是否發(fā)生了交換,如果是,我們則進(jìn)行下一輪,如果沒有,說明已經(jīng)冒泡好了 for (int i = 1; i < arr.length && flag; i++) { //控制次數(shù),第幾趟排序,只需要n-1趟,有交換時進(jìn)行,只有flag=false就說明上一次一個元素都沒有進(jìn)行交換 /*System.out.print("第"+i+"次遍歷:"); for (int i1 : arr) { System.out.print(i1+" "); } System.out.println();*/ flag = false; //假定未交換 for (int j = 0; j < arr.length - i; j++) { if (ascending ? arr[j] > arr[j + 1] : arr[j] < arr[j + 1]) { //控制升序還是降序 int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; flag = true; } } } } //冒泡排序 -- 默認(rèn)不傳參升序 public static void bubbleSort(int[] arr) { bubbleSort(arr, true); } }
測試代碼:
升序排序(從小到大)
package com.keafmd.Sequence; import java.util.*; import java.util.stream.IntStream; import java.util.stream.Stream; /** * Keafmd * * @ClassName: Sort * @Description: 十大排序算法 * @author: 牛哄哄的柯南 * @date: 2021-06-16 21:27 */ public class Sort { public static void main(String[] args) { int[] nums = {12, 4, 25, 47, 58, 34, 25, 9, 99, 26, 1, -13, 162, 10093, -66, -1}; int[] temparr; //測試冒泡排序 System.out.println("測試冒泡排序:"); temparr = nums.clone(); BubbleSort.bubbleSort(temparr); //逆序排序 //BubbleSort.bubbleSort(temparr,false); for (int i = 0; i < temparr.length; i++) { System.out.print(temparr[i] + " "); } System.out.println(); } }
運(yùn)行結(jié)果:
測試冒泡排序: -66 -13 -1 1 4 9 12 25 25 26 34 47 58 99 162 10093
降序排序(從大到?。?/p>
//測試冒泡排序 System.out.println("測試冒泡排序:"); temparr = nums.clone(); BubbleSort.bubbleSort(temparr,false); for (int i = 0; i < temparr.length; i++) { System.out.print(temparr[i] + " "); } System.out.println();
運(yùn)行結(jié)果:
測試冒泡排序: 10093 162 99 58 47 34 26 25 25 12 9 4 1 -1 -13 -66
下面幾個算法的測試也就是換了下類名和方法名(換成相應(yīng)的排序算法),如果想降序就在數(shù)組后面?zhèn)鱾€false即可。我就不一一復(fù)制了,我在最下面給出含所有算法的測試類,需要的自取即可。
快速排序
簡單解釋:快速排序就是每次找一個基點(diǎn)(第一個元素),然后兩個哨兵,一個從最前面往后走,一個從最后面往前面走,如果后面那個哨兵找到了一個比基點(diǎn)大的數(shù)停下來,前面那個哨兵找到比基點(diǎn)大的數(shù)停下來,然后交換兩個哨兵找到的數(shù),如果找不到最后兩個哨兵就會碰到一起就結(jié)束,最后交換基點(diǎn)和哨兵相遇的地方的元素,然后就將一個序列分為比基點(diǎn)小的一部分和比基點(diǎn)大的一部分,然后遞歸左半部分和右半部分,最后的結(jié)果就是有序的了。
完整代碼:
package com.keafmd.Sequence; /** * Keafmd * * @ClassName: QuickSort * @Description: 快速排序 * @author: 牛哄哄的柯南 * @date: 2021-06-24 10:32 */ public class QuickSort { //快速排序 public static void quickSort(int[] arr) { quickSort(arr, true); } public static void quickSort(int[] arr, boolean ascending) { if (ascending) { quickSort(arr, 0, arr.length - 1, true); } else { quickSort(arr, 0, arr.length - 1, false); } } public static void quickSort(int[] arr, int begin, int end, boolean ascending) { if (ascending) quickSort(arr, begin, end); else quickSortDescending(arr, begin, end); } //快排序升序 -- 默認(rèn) public static void quickSort(int[] arr, int begin, int end) { if (begin > end) { //結(jié)束條件 return; } int base = arr[begin]; int i = begin, j = end; while (i < j) { // 兩個哨兵(i左邊,j右邊)沒有相遇 while (arr[j] >= base && i < j) { //哨兵j沒找到比base小的 j--; } while (arr[i] <= base && i < j) { //哨兵i沒找到比base大的 i++; } if (i < j) { //如果滿足條件則交換 int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } //最后將基準(zhǔn)為與i和j相等位置的數(shù)字交換 arr[begin] = arr[i]; arr[i] = base; quickSort(arr, begin, i - 1); //遞歸調(diào)用左半數(shù)組 quickSort(arr, i + 1, end); //遞歸調(diào)用右半數(shù)組 } //快排序降序 public static void quickSortDescending(int[] arr, int begin, int end) { if (begin > end) { //結(jié)束條件 return; } int base = arr[begin]; int i = begin, j = end; while (i < j) { // 兩個哨兵(i左邊,j右邊)沒有相遇 while (arr[j] <= base && i < j) { //哨兵j沒找到比base大的 j--; } while (arr[i] >= base && i < j) { //哨兵i沒找到比base小的 i++; } if (i < j) { //如果滿足條件則交換 int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } //最后將基準(zhǔn)為與i和j相等位置的數(shù)字交換 arr[begin] = arr[i]; arr[i] = base; quickSortDescending(arr, begin, i - 1); //遞歸調(diào)用左半數(shù)組 quickSortDescending(arr, i + 1, end); //遞歸調(diào)用右半數(shù)組 } }
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
SpringBoot項目讀取外置logback配置文件的問題及解決
SpringBoot項目讀取外置logback配置文件的問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08idea hibernate jpa 生成實(shí)體類的實(shí)現(xiàn)
這篇文章主要介紹了idea hibernate jpa 生成實(shí)體類的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Java Calendar類使用總結(jié)及使用實(shí)例
這篇文章主要介紹了Java Calendar類使用總結(jié)及使用實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03eclipse連接數(shù)據(jù)庫并實(shí)現(xiàn)用戶注冊登錄功能
這篇文章主要介紹了eclipse連接數(shù)據(jù)庫并實(shí)現(xiàn)用戶注冊登錄功能的相關(guān)資料,需要的朋友可以參考下2021-01-01SpringBoot redis分布式緩存實(shí)現(xiàn)過程解析
這篇文章主要介紹了SpringBoot redis分布式緩存實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-10-10詳解SpringBoot 創(chuàng)建定時任務(wù)(配合數(shù)據(jù)庫動態(tài)執(zhí)行)
本篇文章主要介紹了SpringBoot 創(chuàng)建定時任務(wù)(配合數(shù)據(jù)庫動態(tài)執(zhí)行),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10Spring?MVC請求轉(zhuǎn)發(fā)與請求重定向的示例詳解
轉(zhuǎn)發(fā)指服務(wù)器接收請求后,從一個資源跳轉(zhuǎn)到另一個資源中,請求轉(zhuǎn)發(fā)是一次請求,不會改變?yōu)g覽器的請求地址,這篇文章主要介紹了Spring?MVC請求轉(zhuǎn)發(fā)與請求重定向的相關(guān)知識,需要的朋友可以參考下2023-09-09Spring?Security自定義登錄頁面認(rèn)證過程常用配置
這篇文章主要為大家介紹了Spring?Security自定義登錄頁面認(rèn)證過程常用配置示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08