日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

常见的算法排序(2)

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

?前言?

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

文章目錄

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

🚄1 快速排序

🚅1.1 快排原理

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

🚈1.2 遞歸實現

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

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));}/*** 快排遞歸寫法* 時間復雜度: 最好 O(N*logN) 最差(有序) O(N*N)* 空間復雜度: O(logN) * 穩定性:不穩定* @param array 待排序數列*/public static void Quack(int[] array){QuackSort(array,0,array.length-1);}public static void QuackSort(int[] array,int left,int right){//遞歸的終止條件,當左等于大于右時,說明此時序列有序if(left>=right){return;}//找基準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 對快排進行優化(三數取中法)

對于快排的優化,其實就是優化基準:

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));}/*** 快排遞歸寫法* 時間復雜度: 最好 O(N*logN) 最差(有序) O(N*N)* 空間復雜度: O(logN)* 穩定性:不穩定* @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){//遞歸的終止條件,當左等于大于右時,說明此時序列有序if(left>=right){return;}//獲取三個值中間值的小標int mid = getMid(array,left,right);//在把中間值放到一開始的位置Swap(array,left,mid);//找基準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 快排的優化實質上就是在對基準進行優化,所以這里采用了三數取中法進行優化
2 可以結合我們之前所學的直接插入排序進行優化,對于插入排序,之前已經了解到數列越有序越快,那么就可以當調整的長度小于某個數的時候,可以直接利用直接插入排序

🚃1.4 非遞歸實現

對于非遞歸的實現,我們此時還是一樣根據原理需要找到基準值,然后再利用數據結構中棧去解決(核心的思想也是利用找基準去解決):
代碼如下:

//非遞歸實現public static void nonQuackSort(int[] array){int start = 0;int end = array.length-1;Stack<Integer> stack = new Stack<>();//找基準int 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);}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 歸并的核心思想

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

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

🚎2.2 歸并排序的遞歸實現

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;}//左邊遞歸進行分解merge(array,low,mid);//右邊遞歸進行分解merge(array,mid+1,high);//開始歸并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++];}}//可能存在第一個數組沒放完或者第二個數組的數據沒放完while (s1<=e1){tmp[i++]=array[s1++];}while (s2<=e2){tmp[i++]=array[s2++];}}for (int j = 0; j < i; j++) {//注意數組下標,當遇到右邊數組合并時,它的第一個下標已經不是零了array[j+low]=tmp[j];}}

🚍2.3 歸并排序的非遞歸實現

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

public static void nonmergeSort(int[] array){//組數(一開始一個一組)int gap = 1;//只有組數大于等于數組的長度,那么此時說明數組已經有序while (gap<array.length){//每重新分組,遍歷一遍數組,進行歸并排序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;}//開始歸并Conbine(array,left,mid,right);}//循環結束,組數乘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++];}}//可能存在第一個數組沒放完或者第二個數組的數據沒放完while (s1<=e1){tmp[i++]=array[s1++];}while (s2<=e2){tmp[i++]=array[s2++];}}for (int j = 0; j < i; j++) {//注意數組下標,當遇到右邊數組合并時,它的第一個下標已經不是零了array[j+low]=tmp[j];}}

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

🚖3.1 計數排序

計數排序詳解

🚘3.2 基數排序

基數排序詳解

🚔3.3 桶排序

桶排序詳解

🚉4 總結

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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。