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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法图解之快速排序

發(fā)布時(shí)間:2025/5/22 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法图解之快速排序 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

分而治之(又稱D&C)

書中舉了一個(gè)例子,假設(shè)你是農(nóng)場主,有一塊土地,如圖所示:

?

你要將這塊地均勻分成方塊,且分出的方塊要盡可能大。

?

?

從圖上看,顯然是不符合預(yù)期結(jié)果的。

那么如何將一塊地均勻分成方塊,并確保分出的方塊是最大的呢?使用D&C策略。

(1)D&C算法是遞歸的;
(2)使用D&C解決問題的過程包括兩個(gè)步驟:
a.找出基線條件,這種條件必須盡可能簡單;
b.不斷將問題分解(或者說縮小規(guī)模),直到符合基線條件;

就如何保證分出的方塊是最大的呢?《算法圖解》中的快速排序一章提到了歐幾里得算法。

什么是歐幾里得算法?
歐幾里得算法又稱輾轉(zhuǎn)相除法,是指用于計(jì)算兩個(gè)正整數(shù)a,b的最大公約數(shù)。
應(yīng)用領(lǐng)域有數(shù)學(xué)和計(jì)算機(jī)兩個(gè)方面。

舉個(gè)代碼例子說一下歐幾里得算法:

package cn.pratice.simple;public class Euclid {public static void main(String[] args) {int m = 63;int n = 18;int remainer = 0;while(n!=0) {remainer = m % n;m = n;n = remainer;}System.out.println(m);} }

?

最終的結(jié)果是9,正好63和18的最大公因數(shù)也是9.
其中也體現(xiàn)著分而治之的思想。記住,分而治之并非可用于解決問題的算法而是一種解決問題的思路。

再舉個(gè)例子說明,如圖所示:

?

需要將這些數(shù)字相加,并返回結(jié)果,使用循環(huán)很容易完成這種任務(wù),以Java為例:

?

package cn.pratice.simple;public class Euclid {public static void main(String[] args) {int []num = new int[] {2,4,6};int total = 0;for (int i = 0; i < num.length; i++) {total += num[i];}System.out.println(total);} }

快速排序

快速排序是一種常用的排序算法,比選擇排序快的多。
代碼示例如下(快速排序):

package cn.pratice.simple;public class QuickSort {//聲明靜態(tài)的 getMiddle() 方法,該方法需要返回一個(gè) int 類型的參數(shù)值,在該方法中傳入 3 個(gè)參數(shù)public static int getMiddle(int[] list,int low,int high) {int tmp = list[low];//數(shù)組的第一個(gè)值作為中軸(分界點(diǎn)或關(guān)鍵數(shù)據(jù))while(low<high) {while(low<high && list[high]>tmp) {high--;}list[low] = list[high];//比中軸小的記錄移到低端while(low<high&&list[low]<tmp) {low++;}list[high]=list[low];//比中軸大的記錄移到高端 }list[low] = tmp;//中軸記錄到尾return low;}//創(chuàng)建靜態(tài)的 unckSort() 方法,在該方法中判斷 low 參數(shù)是否小于 high 參數(shù),如果是則調(diào)用 getMiddle() 方法,將數(shù)組一分為二,并且調(diào)用自身的方法進(jìn)行遞歸排序public static void unckSort(int[] list,int low,int high) {if(low<high) {int middle = getMiddle(list,low,high);//將list數(shù)組一分為二unckSort(list,low,middle-1);//對低字表進(jìn)行遞歸排序unckSort(list,middle+1,high);//對高字表進(jìn)行遞歸排序 }}//聲明靜態(tài)的 quick() 方法,在該方法中判斷傳入的數(shù)組是否為空,如果不為空,則調(diào)用 unckSort() 方法進(jìn)行排序public static void quick(int[] str) {if(str.length>0) {//查看數(shù)組是否為空unckSort(str,0,str.length-1);}}//測試public static void main(String[] args) {int[] number = {13,15,24,99,14,11,1,2,3};System.out.println("排序前:");for (int i : number) {System.out.print(i+" ");}quick(number);System.out.println("\r排序后:");for (int i : number) {System.out.print(i+" ");}} }

此示例來自Java數(shù)組排序:Java快速排序(Quicksort)法

沒有什么比代碼示例來的直接痛快。

再談大O表示法

快速排序的獨(dú)特之處在于,其速度取決于選擇的基準(zhǔn)值。

常見的大O運(yùn)行時(shí)間圖,如下:

?

上述圖表中的時(shí)間是基于每秒執(zhí)行10次操作計(jì)算得到的。這些數(shù)據(jù)并不準(zhǔn)確,這里提供它們只是想讓你對這些運(yùn)行時(shí)間的差別有大致認(rèn)識(shí)。實(shí)際上,計(jì)算機(jī)每秒執(zhí)行的操作遠(yuǎn)遠(yuǎn)不止10次。 在該節(jié)中,作者說合并排序比選擇排序要快的多。合并排序,用數(shù)學(xué)公式表示為O(n log n),而選擇排序?yàn)镺(n的2次方)。
合并代碼排序例子如下:

package cn.pratice.simple;import java.util.Arrays;public class MergeSort {private static void mergeSort(int[] original) {if (original == null) {throw new NullPointerException("The array can not be null !!!");}int length = original.length;if (length > 1) {int middle = length / 2;int partitionA[] = Arrays.copyOfRange(original, 0, middle);// 拆分問題規(guī)模int partitionB[] = Arrays.copyOfRange(original, middle, length);// 遞歸調(diào)用 mergeSort(partitionA);mergeSort(partitionB);sort(partitionA, partitionB, original);}}private static void sort(int[] partitionA, int[] partitionB, int[] original) {int i = 0;int j = 0;int k = 0;while (i < partitionA.length && j < partitionB.length) {if (partitionA[i] <= partitionB[j]) {original[k] = partitionA[i];i++;} else {original[k] = partitionB[j];j++;}k++;}if (i == partitionA.length) {while (k < original.length) {original[k] = partitionB[j];k++;j++;}} else if (j == partitionB.length) {while (k < original.length) {original[k] = partitionA[i];k++;i++;}}}private static void print(int[] array) {if (array == null) {throw new NullPointerException("The array can not be null !!!");}StringBuilder sb = new StringBuilder("[");for (int element : array) {sb.append(element + ", ");}sb.replace(sb.length() - 2, sb.length(), "]");System.out.println(sb.toString());}public static void main(String[] args) {long startTime = System.currentTimeMillis(); //獲取開始時(shí)間int original[] = new int[] { 13,15,24,99,14,11,1,2,3 };for (int i = 0; i < original.length; i++) {System.out.print(original[i]+" ");}mergeSort(original);print(original);long endTime = System.currentTimeMillis(); //獲取結(jié)束時(shí)間 System.out.println("程序運(yùn)行時(shí)間:" + (endTime - startTime) + "ms"); //輸出程序運(yùn)行時(shí)間 } }

此示例來自
java實(shí)現(xiàn)合并排序算法

比較快速排序與合并排序

還是以上面的代碼例子為例:
快速排序代碼例子,如下:

public static int getMiddle(int[] list,int low,int high) {int tmp = list[low];//數(shù)組的第一個(gè)值作為中軸(分界點(diǎn)或關(guān)鍵數(shù)據(jù))while(low<high) {while(low<high && list[high]>tmp) {high--;}list[low] = list[high];//比中軸小的記錄移到低端while(low<high&&list[low]<tmp) {low++;}list[high]=list[low];//比中軸大的記錄移到高端 }list[low] = tmp;//中軸記錄到尾return low;}//創(chuàng)建靜態(tài)的 unckSort() 方法,在該方法中判斷 low 參數(shù)是否小于 high 參數(shù),如果是則調(diào)用 getMiddle() 方法,將數(shù)組一分為二,并且調(diào)用自身的方法進(jìn)行遞歸排序public static void unckSort(int[] list,int low,int high) {if(low<high) {int middle = getMiddle(list,low,high);//將list數(shù)組一分為二unckSort(list,low,middle-1);//對低字表進(jìn)行遞歸排序unckSort(list,middle+1,high);//對高字表進(jìn)行遞歸排序 }}//聲明靜態(tài)的 quick() 方法,在該方法中判斷傳入的數(shù)組是否為空,如果不為空,則調(diào)用 unckSort() 方法進(jìn)行排序public static void quick(int[] str) {if(str.length>0) {//查看數(shù)組是否為空unckSort(str,0,str.length-1);}}//測試public static void main(String[] args) {long startTime = System.currentTimeMillis(); //獲取開始時(shí)間int[] number = { 13,15,24,99,14,11,1,2,3,2,32,4321,432,3,14,153,23,42,12,34,15,312,12,43,3214,43214,43214,43214,12,2432,12,34,24,4532,1234};quick(number);for (int i : number) {System.out.print(i+" ");}long endTime = System.currentTimeMillis(); //獲取結(jié)束時(shí)間 System.out.println("程序運(yùn)行時(shí)間:" + (endTime - startTime) + "ms"); //輸出程序運(yùn)行時(shí)間 } }

輸出結(jié)果,如圖:

半天看不到輸出結(jié)果,而程序仍在運(yùn)行中。如果將數(shù)組中的元素還原為原來那幾個(gè),則很快看到結(jié)果。

合并代碼例子,如下:

package cn.pratice.simple;import java.util.Arrays;public class MergeSort {private static void mergeSort(int[] original) {if (original == null) {throw new NullPointerException("The array can not be null !!!");}int length = original.length;if (length > 1) {int middle = length / 2;int partitionA[] = Arrays.copyOfRange(original, 0, middle);// 拆分問題規(guī)模int partitionB[] = Arrays.copyOfRange(original, middle, length);// 遞歸調(diào)用 mergeSort(partitionA);mergeSort(partitionB);sort(partitionA, partitionB, original);}}private static void sort(int[] partitionA, int[] partitionB, int[] original) {int i = 0;int j = 0;int k = 0;while (i < partitionA.length && j < partitionB.length) {if (partitionA[i] <= partitionB[j]) {original[k] = partitionA[i];i++;} else {original[k] = partitionB[j];j++;}k++;}if (i == partitionA.length) {while (k < original.length) {original[k] = partitionB[j];k++;j++;}} else if (j == partitionB.length) {while (k < original.length) {original[k] = partitionA[i];k++;i++;}}}private static void print(int[] array) {if (array == null) {throw new NullPointerException("The array can not be null !!!");}StringBuilder sb = new StringBuilder("[");for (int element : array) {sb.append(element + ", ");}sb.replace(sb.length() - 2, sb.length(), "]");System.out.println(sb.toString());}public static void main(String[] args) {long startTime = System.currentTimeMillis(); //獲取開始時(shí)間int original[] = new int[] { 13,15,24,99,14,11,1,2,3,2,32,4321,432,3,14,153,23,42,12,34,15,312,12,43,3214,43214,43214,43214,12,2432,12,34,24,4532,1234};for (int i = 0; i < original.length; i++) {System.out.print(original[i]+" ");}mergeSort(original);print(original);long endTime = System.currentTimeMillis(); //獲取結(jié)束時(shí)間 System.out.println("程序運(yùn)行時(shí)間:" + (endTime - startTime) + "ms"); //輸出程序運(yùn)行時(shí)間 } }

輸出結(jié)果,如圖:

通過兩者對比,我們很容易得出合并排序比快速排序快。

參考這個(gè)合并排序和快速排序執(zhí)行時(shí)間比較

作者通過實(shí)驗(yàn)得出一個(gè)結(jié)論:當(dāng)數(shù)據(jù)量較小的時(shí)候,快速排序比合并排序運(yùn)行時(shí)間要短,運(yùn)行時(shí)間短就表示快,但是當(dāng)數(shù)據(jù)量大的時(shí)候,合并排序比快速排序運(yùn)行時(shí)間要短
由此通過我上述的代碼實(shí)驗(yàn)和該文章作者試驗(yàn),可證實(shí)這個(gè)結(jié)論。

轉(zhuǎn)載于:https://www.cnblogs.com/youcong/p/10957896.html

總結(jié)

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

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

主站蜘蛛池模板: 肉色超薄丝袜脚交一区二区图片 | 少妇人妻丰满做爰xxx | 奇米四色7777 | 性――交――性――乱 | 久久久久久69 | 蜜桃导航-精品导航 | 午夜福利视频合集1000 | 久久99热这里只有精品 | 日韩在线观看免费网站 | 国产精品视频久久久久久 | 久久人人爽爽 | 亚洲激情视频在线 | 青青草手机在线视频 | 精品成人无码一区二区三区 | 国产区第一页 | 国产综合无码一区二区色蜜蜜 | 国产视频一区在线观看 | 男女调教视频 | 波多野结衣视频网站 | 国产麻豆一级片 | 91麻豆精品秘密入口 | 成人香蕉视频在线观看 | 成人黄色小说视频 | 高清一区二区在线 | 最新国产一区 | 国产一二区在线观看 | 欧美福利在线视频 | 亚洲国产精品国自产拍久久 | 亚洲精品三级 | 久久婷婷国产麻豆91 | 亚洲一区电影 | 日韩一区中文字幕 | 欧美wwwwww | 夜福利视频 | xxxx日本免费 | av免费大片| 日韩精品一区二区三区久久 | 懂色av一区二区夜夜嗨 | 亚洲一区二区影视 | 在线观看日本 | 视频一区欧美 | 国产精品久久久久高潮 | 色妞网站 | 免费观看一级视频 | 免费黄色网址在线观看 | 国产91免费看 | 岛国毛片在线观看 | 国产视频精品一区二区三区 | 久久婷婷影院 | 国产精品亚洲一区二区无码 | 天天舔天天射 | 成年人视频在线免费看 | 久久小草 | 日日爱99 | 欧美色激情 | 天天艹天天操 | 高清国产一区二区三区四区五区 | 插插插91| 99视频在线免费观看 | 粉嫩一区二区三区 | 狠操av | 在线观看h网站 | 天堂影院一区二区 | 欧美一级黄色片在线观看 | 欧美午夜精品理论片a级按摩 | 免费观看黄色网 | 麻豆传媒网站在线观看 | 成人日皮视频 | 97色干| 色91视频| 亚洲乱码中文字幕 | 日韩中文字幕一区二区三区 | 蜜臀久久精品 | 好了av在线 | 秋霞精品| 91麻豆国产在线 | 欧美 日韩 国产 中文 | 男生操女生动漫 | 少妇做爰免费理伦电影 | 91亚洲在线 | 外国电影免费观看高清完整版 | 久久成年网 | 国产肉体xxxx裸体784大胆 | 亚洲熟女乱综合一区二区 | 强videoshd酒醉 | 爱的色放3| 亚洲色在线视频 | 大奶av| 福利国产视频 | 成人高潮片 | 色亚洲欧美 | 强侵犯の奶水授乳羞羞漫虐 | 久久久久久久久久成人 | 一色桃子juy758在线播放 | 精品三级电影 | av在线播放器 | 日韩欧美精品免费 | 瑟瑟综合网 | 超污视频网站 |