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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 归并排序 非递归_归并排序-递归及非递归的JAVA实现

發(fā)布時間:2024/4/13 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 归并排序 非递归_归并排序-递归及非递归的JAVA实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

歸并排序介紹

平均時間復雜度: O(NLogN)

最好情況時間復雜度: O(NLogN)

最差情況時間復雜度: O(NLogN)

所需要額外空間: 遞歸:O(N + LogN), 非遞歸:O(N)

穩(wěn)定性: 穩(wěn)定

歸并排序基于分治(快排也是),利用歸并來實現(xiàn)排序,其基本思想是:

如果一個數組有n個數據,則可以把這個數組看作n個有序的子序列,每個子序列的長度為1,然后兩兩歸并,就能得到[n/2]個長度為2(或者1,落單的)的字序列,再不斷地兩兩歸并,直到得到一個長度為n的有序數組。

這里選擇Merge就能比較直觀地看到歸并排序的過程。

使用遞歸的歸并排序

理解這個基本思想后,就不難寫出歸并排序的代碼,只要遞歸地進行歸并就行了.

其中歸并函數merge也很好理解,就是合并兩個有序數組為一個有序數組即可。

package com.yenghye.sort;

public class Sort {

public static void MergeSort(int[] arr, int low, int high)

{

//使用遞歸的方式進行歸并排序,所需要的空間復雜度是O(N+logN)

int mid = (low + high)/2;

if(low < high)

{

//遞歸地對左右兩邊進行排序

MergeSort(arr, low, mid);

MergeSort(arr, mid+1, high);

//合并

merge(arr, low, mid, high);

}

}

//merge函數實際上是將兩個有序數組合并成一個有序數組

//因為數組有序,合并很簡單,只要維護幾個指針就可以了

private static void merge(int[] arr, int low, int mid, int high)

{

//temp數組用于暫存合并的結果

int[] temp = new int[high - low + 1];

//左半邊的指針

int i = low;

//右半邊的指針

int j = mid+1;

//合并后數組的指針

int k = 0;

//將記錄由小到大地放進temp數組

for(; i <= mid && j <= high; k++)

{

if(arr[i] < arr[j])

temp[k] = arr[i++];

else

temp[k] = arr[j++];

}

//接下來兩個while循環(huán)是為了將剩余的(比另一邊多出來的個數)放到temp數組中

while(i <= mid)

temp[k++] = arr[i++];

while(j <= high)

temp[k++] = arr[j++];

//將temp數組中的元素寫入到待排數組中

for(int l = 0; l < temp.length; l++)

arr[low + l] = temp[l];

}

}

歸并排序的優(yōu)化(非遞歸歸并排序)

但是,使用遞歸的歸并排序需要深度為LogN的棧空間,雖然代碼很簡單易懂,但是會造成時間和空間上的性能損耗,為了優(yōu)化歸并排序,我們可以使用迭代代替遞歸。

package com.yenghye.sort;

public class Sort {

public static void MergeSort2(int[] arr)

{

//使用非遞歸的方式來實現(xiàn)歸并排序

int len = arr.length;

int k = 1;

while(k < len)

{

MergePass(arr, k, len);

k *= 2;

}

}

//MergePass方法負責將數組中的相鄰的有k個元素的字序列進行歸并

private static void MergePass(int[] arr, int k, int n)

{

int i = 0;

int j;

//從前往后,將2個長度為k的子序列合并為1個

while(i < n - 2*k + 1)

{

merge(arr, i, i + k-1, i + 2*k - 1);

i += 2*k;

}

//這段代碼保證了,將那些“落單的”長度不足兩兩merge的部分和前面merge起來。

if(i < n - k )

{

merge(arr, i, i+k-1, n-1);

}

}

//merge函數實際上是將兩個有序數組合并成一個有序數組

//因為數組有序,合并很簡單,只要維護幾個指針就可以了

private static void merge(int[] arr, int low, int mid, int high)

{

//temp數組用于暫存合并的結果

int[] temp = new int[high - low + 1];

//左半邊的指針

int i = low;

//右半邊的指針

int j = mid+1;

//合并后數組的指針

int k = 0;

//將記錄由小到大地放進temp數組

for(; i <= mid && j <= high; k++)

{

if(arr[i] < arr[j])

temp[k] = arr[i++];

else

temp[k] = arr[j++];

}

//接下來兩個while循環(huán)是為了將剩余的(比另一邊多出來的個數)放到temp數組中

while(i <= mid)

temp[k++] = arr[i++];

while(j <= high)

temp[k++] = arr[j++];

//將temp數組中的元素寫入到待排數組中

for(int l = 0; l < temp.length; l++)

arr[low + l] = temp[l];

}

}

非遞歸而是迭代的歸并排序很直觀,就是從前往后從最小的序列開始歸并,直到完成即可。

但是這里邊界條件不太好想,要注意不要出錯。

總結

以上是生活随笔為你收集整理的java 归并排序 非递归_归并排序-递归及非递归的JAVA实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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