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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

常见的算法排序(2)

發(fā)布時間:2025/3/20 编程问答 9 豆豆
生活随笔 收集整理的這篇文章主要介紹了 常见的算法排序(2) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?前言?

📘 博客主頁:to Keep博客主頁
🙆歡迎關(guān)注,👍點(diǎn)贊,📝留言評論
?首發(fā)時間:2022年3月1日
📨 博主碼云地址:博主碼云地址
📕參考書籍:java核心技術(shù) 卷1
📢編程練習(xí):牛客網(wǎng)+力扣網(wǎng)
由于博主目前也是處于一個學(xué)習(xí)的狀態(tài),如有講的不對的地方,請一定聯(lián)系我予以改正!!!

文章目錄

  • 🚄1 快速排序
    • 🚅1.1 快排原理
    • 🚈1.2 遞歸實(shí)現(xiàn)
    • 🚝1.3 對快排進(jìn)行優(yōu)化(三數(shù)取中法)
    • 🚃1.4 非遞歸實(shí)現(xiàn)
  • 🚋二 歸并排序
    • 🚌2.1 歸并的核心思想
    • 🚎2.2 歸并排序的遞歸實(shí)現(xiàn)
    • 🚍2.3 歸并排序的非遞歸實(shí)現(xiàn)
  • 🚗三 其他排序(非基于比較)
    • 🚖3.1 計數(shù)排序
    • 🚘3.2 基數(shù)排序
    • 🚔3.3 桶排序
  • 🚉4 總結(jié)

🚄1 快速排序

🚅1.1 快排原理

1 從待排序區(qū)間選擇一個數(shù),作為基準(zhǔn)值
2 遍歷整個待排序區(qū)間,將比基準(zhǔn)值小的(可以包含相等的)放到基準(zhǔn)值的左邊,將比基準(zhǔn)值大的(可以包含相等的)放到基準(zhǔn)值的右邊;
3 采用分治思想對左右兩個小區(qū)間,對左右兩個小區(qū)間按照同樣的方式來處理,直到小區(qū)間的長度==1,那么表面已經(jīng)有序,如果長度為零,則說明沒有數(shù)據(jù)!

🚈1.2 遞歸實(shí)現(xiàn)

通過了解快排的原理,那么就可以編寫如下代碼(我們一開始以數(shù)列中第一個數(shù)為基準(zhǔn)值,尋找基準(zhǔn)在數(shù)列中所在的位置):

public class TestDemo1 {public static void main(String[] args) {int[] array = {67,7,32,98,1,0,45,23,234,6746,123};Quack(array);System.out.println(Arrays.toString(array));}/*** 快排遞歸寫法* 時間復(fù)雜度: 最好 O(N*logN) 最差(有序) O(N*N)* 空間復(fù)雜度: O(logN) * 穩(wěn)定性:不穩(wěn)定* @param array 待排序數(shù)列*/public static void Quack(int[] array){QuackSort(array,0,array.length-1);}public static void QuackSort(int[] array,int left,int right){//遞歸的終止條件,當(dāng)左等于大于右時,說明此時序列有序if(left>=right){return;}//找基準(zhǔn)int privot = getprivot(array,left,right);//遞歸左邊QuackSort(array,left,privot-1);//遞歸右邊QuackSort(array,privot+1,right);}public static int getprivot(int[] array,int start,int end){int tmp = array[start];while (start<end){while (start<end&&array[end]>=tmp){end--;}array[start]=array[end];while (start<end&&array[start]<=tmp){start++;}array[end]=array[start];}array[start]=tmp;return start;} }

🚝1.3 對快排進(jìn)行優(yōu)化(三數(shù)取中法)

對于快排的優(yōu)化,其實(shí)就是優(yōu)化基準(zhǔn):

public class TestDemo1 {public static void main(String[] args) {int[] array = {67,7,32,98,1,0,45,23,234,6746,123};Quack(array);System.out.println(Arrays.toString(array));}/*** 快排遞歸寫法* 時間復(fù)雜度: 最好 O(N*logN) 最差(有序) O(N*N)* 空間復(fù)雜度: O(logN)* 穩(wěn)定性:不穩(wěn)定* @param array*/public static void Quack(int[] array){QuackSort(array,0,array.length-1);}public static void Swap(int[] array,int i,int j){int tmp = array[i];array[i]=array[j];array[j]=tmp;}public static int getMid(int[] array,int a,int b){int mid = a+((b-a)>>>1);if(array[a]>array[b]){if(array[mid]>array[a]){return a;}else if(array[mid]<array[b]){return b;}else{return mid;}}else{//array[a]<array[b]if(array[mid]<array[a]){return a;}else if(array[mid]>array[b]){return b;}else{return mid;}}}public static void QuackSort(int[] array,int left,int right){//遞歸的終止條件,當(dāng)左等于大于右時,說明此時序列有序if(left>=right){return;}//獲取三個值中間值的小標(biāo)int mid = getMid(array,left,right);//在把中間值放到一開始的位置Swap(array,left,mid);//找基準(zhǔn)int privot = getprivot(array,left,right);//遞歸左邊QuackSort(array,left,privot-1);//遞歸右邊QuackSort(array,privot+1,right);}public static int getprivot(int[] array,int start,int end){int tmp = array[start];while (start<end){while (start<end&&array[end]>=tmp){end--;}array[start]=array[end];while (start<end&&array[start]<=tmp){start++;}array[end]=array[start];}array[start]=tmp;return start;} }

優(yōu)化總結(jié):
1 快排的優(yōu)化實(shí)質(zhì)上就是在對基準(zhǔn)進(jìn)行優(yōu)化,所以這里采用了三數(shù)取中法進(jìn)行優(yōu)化
2 可以結(jié)合我們之前所學(xué)的直接插入排序進(jìn)行優(yōu)化,對于插入排序,之前已經(jīng)了解到數(shù)列越有序越快,那么就可以當(dāng)調(diào)整的長度小于某個數(shù)的時候,可以直接利用直接插入排序

🚃1.4 非遞歸實(shí)現(xiàn)

對于非遞歸的實(shí)現(xiàn),我們此時還是一樣根據(jù)原理需要找到基準(zhǔn)值,然后再利用數(shù)據(jù)結(jié)構(gòu)中棧去解決(核心的思想也是利用找基準(zhǔn)去解決):
代碼如下:

//非遞歸實(shí)現(xiàn)public static void nonQuackSort(int[] array){int start = 0;int end = array.length-1;Stack<Integer> stack = new Stack<>();//找基準(zhǔn)int privot = getprivot(array,start,end);//確保右邊至少有兩個可排序的數(shù),否則就是只有一個數(shù),就是有序的if(privot-1>start){stack.push(start);stack.push(privot-1);}//確保左邊至少有兩個可排序的數(shù),否則就是只有一個數(shù),就是有序的if(privot+1<end){stack.push(privot+1);stack.push(end);}while (!stack.isEmpty()){end=stack.pop();start=stack.pop();privot = getprivot(array,start,end);if(privot-1>start){stack.push(start);stack.push(privot-1);}if(privot+1<end){stack.push(privot+1);stack.push(end);}}}

🚋二 歸并排序

🚌2.1 歸并的核心思想

給定兩個有序數(shù)組,那么如何將他們合并成為一個有序的數(shù)組呢?其實(shí)在合并的過程中就體現(xiàn)出歸并排序的初步思想原理,就是依據(jù)這樣的一個思想。
代碼如下:

public static int[] conbine(int[] array1,int[] array2){//創(chuàng)建一個新的數(shù)組來存儲合并之后的數(shù)據(jù)int[] array = new int[array1.length+array2.length];//記錄合并數(shù)組的下標(biāo)int i = 0;//第一個數(shù)組的第一個下標(biāo)int s1 = 0;//第一個數(shù)組的最后一個下標(biāo)int e1 = array1.length-1;//第二個數(shù)組的第一個下標(biāo)int s2 = 0;//第二個數(shù)組的最后一個下標(biāo)int e2 = array2.length-1;//將兩個數(shù)組中的數(shù)據(jù)按照從小到大放入新的數(shù)組中while (s1<=e1&&s2<=e2){if(array1[s1]<array2[s2]){array[i++]=array1[s1++];}else{array[i++]=array2[s2++];}}//可能存在第一個數(shù)組沒放完或者第二個數(shù)組的數(shù)據(jù)沒放完while (s1<=e1){array[i++]=array1[s1++];}while (s2<=e2){array[i++]=array2[s2++];}return array;}

🚎2.2 歸并排序的遞歸實(shí)現(xiàn)

public static void mergeSort(int[] array){merge(array,0,array.length-1);}public static void merge(int[] array,int low,int high){int mid = low+((high-low)>>>1);//遞歸的終止條件if(low>=high){return;}//左邊遞歸進(jìn)行分解merge(array,low,mid);//右邊遞歸進(jìn)行分解merge(array,mid+1,high);//開始?xì)w并Conbine(array,low,mid,high);}//歸并的核心思想public static void Conbine(int[] array,int low,int mid,int high){int[] tmp = new int[high-low+1];int i = 0;int s1 = low;int e1 = mid;int s2 = mid+1;int e2 = high;while (s1<=e1&&s2<=e2){while (s1<=e1&&s2<=e2){if(array[s1]<array[s2]){tmp[i++]=array[s1++];}else{tmp[i++]=array[s2++];}}//可能存在第一個數(shù)組沒放完或者第二個數(shù)組的數(shù)據(jù)沒放完while (s1<=e1){tmp[i++]=array[s1++];}while (s2<=e2){tmp[i++]=array[s2++];}}for (int j = 0; j < i; j++) {//注意數(shù)組下標(biāo),當(dāng)遇到右邊數(shù)組合并時,它的第一個下標(biāo)已經(jīng)不是零了array[j+low]=tmp[j];}}

🚍2.3 歸并排序的非遞歸實(shí)現(xiàn)

非遞歸排序,所采用的思想就是先分組,先是一個一個一組,在變成兩個一組,最后整個數(shù)組為一組時,此時就是一個有序的數(shù)組。

public static void nonmergeSort(int[] array){//組數(shù)(一開始一個一組)int gap = 1;//只有組數(shù)大于等于數(shù)組的長度,那么此時說明數(shù)組已經(jīng)有序while (gap<array.length){//每重新分組,遍歷一遍數(shù)組,進(jìn)行歸并排序for (int i = 0; i < array.length-1; i+=2*gap) {int left = i;int mid = left+gap-1;//注意這時mid可能會越界if (mid>=array.length){mid=array.length-1;}int right = mid+gap;if(right>=array.length){right=array.length-1;}//開始?xì)w并Conbine(array,left,mid,right);}//循環(huán)結(jié)束,組數(shù)乘2gap=gap*2;}}public static void Conbine(int[] array,int low,int mid,int high){int[] tmp = new int[high-low+1];int i = 0;int s1 = low;int e1 = mid;int s2 = mid+1;int e2 = high;while (s1<=e1&&s2<=e2){while (s1<=e1&&s2<=e2){if(array[s1]<array[s2]){tmp[i++]=array[s1++];}else{tmp[i++]=array[s2++];}}//可能存在第一個數(shù)組沒放完或者第二個數(shù)組的數(shù)據(jù)沒放完while (s1<=e1){tmp[i++]=array[s1++];}while (s2<=e2){tmp[i++]=array[s2++];}}for (int j = 0; j < i; j++) {//注意數(shù)組下標(biāo),當(dāng)遇到右邊數(shù)組合并時,它的第一個下標(biāo)已經(jīng)不是零了array[j+low]=tmp[j];}}

🚗三 其他排序(非基于比較)

🚖3.1 計數(shù)排序

計數(shù)排序詳解

🚘3.2 基數(shù)排序

基數(shù)排序詳解

🚔3.3 桶排序

桶排序詳解

🚉4 總結(jié)

可以通過一個表格列舉出這些排序的特點(diǎn),根據(jù)排序的需求,選擇合適的排序方式!

總結(jié)

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

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