1.递归实现的算法思路
① 首先将区间左右均分成两部分,按照此方法不断向下划分,直至区间内只剩一个数据(递归)
② 然后相邻两两区间进行排序归并(递归)
③ 将临时空间temp中的数据拷贝到array中去
代码实现如下:
首先写出一个合并数据的方法:
// 合并数据 [left,mid) [mid,right)
private static void mergeData(int[] array,int left,int mid,int right,int[] temp){
int index=left;
int begin1=left,end1=mid,begin2=mid,end2=right;
while (begin1<end1 && begin2<end2){
if (array[begin1] <= array[begin2]) {
temp[index++]=array[begin1++];
}
else {
temp[index++]=array[begin2++];
}
}
// 如果第一个区间中还有数据
while (begin1<end1){
temp[index++]=array[begin1++];
}
// 如果第二个区间有数据
while (begin2<end2){
temp[index++]=array[begin2++];
}
}
完整代码实现:
// 9.归并排序
private static void mergeSort(int[] array,int left,int right,int[] temp){
if (right-left>1){
int mid=left+((right-left)>>1);
// 1.划分数据
// [left,mid)--->左半部分
mergeSort(array,left,mid,temp);
// [mid,right)--->右半部分
mergeSort(array,mid,right,temp);
// 2.归并数据
mergeData(array,left,mid,right,temp);
// 因为归并好的数据存储在临时空间temp中
// 3. 将temp中的数据拷贝到array中去
System.arraycopy(temp,left,array,left,right-left);
}
}
// 合并数据 [left,mid) [mid,right)
private static void mergeData(int[] array,int left,int mid,int right,int[] temp){
int index=left;
int begin1=left,end1=mid,begin2=mid,end2=right;
while (begin1<end1 && begin2<end2){
if (array[begin1] <= array[begin2]) {
temp[index++]=array[begin1++];
}
else {
temp[index++]=array[begin2++];
}
}
// 如果第一个区间中还有数据
while (begin1<end1){
temp[index++]=array[begin1++];
}
// 如果第二个区间有数据
while (begin2<end2){
temp[index++]=array[begin2++];
}
}
//为了方便用户调用
public static void mergeSort(int[] array){
int[] temp=new int[array.length];
mergeSort(array,0,array.length,temp);
}
public static void printArray(int[] array) {
for (int e : array) {
System.out.print(e + " ");
}
}
public static void main(String[] args) {
int[] array={3,8,9,4,1,5,2,0,6,7};
mergeSort(array);
printArray(array);
}
}
为了用户方便使用,将归并排序与合并数据两个方法定义为私有的,再定义一个同名方法来调用它
时间复杂度:O(NlogN)
空间复杂度:O(N)
稳定性:稳定的
2. 循环实现算法思路
① 定义一个gap,数据以gap的值为组内数据的个数,进行合并排序,同样调用mergeData的方法
② 要注意gap值的变化,以及它的范围不可以超过数组长度
代码如下:
public static void mergeSortNor(int[] array) {
int[] temp = new int[array.length];
int gap = 1;
while (gap < array.length) {
for (int i = 0; i < array.length; i += gap * 2) {
int left = i;
int mid = left + gap;
int right = mid + gap;
if (mid > array.length) {
mid = array.length;
}
if (right > array.length) {
right = array.length;
}
mergeData(array, left, mid, right, temp);
}
System.arraycopy(temp, 0, array, 0, array.length);
gap <<=1;
}
}
// 合并数据 [left,mid) [mid,right)
private static void mergeData(int[] array,int left,int mid,int right,int[] temp){
int index=left;
int begin1=left,end1=mid,begin2=mid,end2=right;
while (begin1<end1 && begin2<end2){
if (array[begin1] <= array[begin2]) {
temp[index++]=array[begin1++];
}
else {
temp[index++]=array[begin2++];
}
}
// 如果第一个区间中还有数据
while (begin1<end1){
temp[index++]=array[begin1++];
}
// 如果第二个区间有数据
while (begin2<end2){
temp[index++]=array[begin2++];
}
}
public static void printArray(int[] array) {
for (int e : array) {
System.out.print(e + " ");
}
}
public static void main(String[] args) {
int[] array={3,8,9,4,1,5,2,0,6,7};
mergeSortNor(array);
printArray(array);
}
}
3. 归并排序(递归实现)的优化
因为数据划分没必要一直划分到1为止,所以可以借助插入排序的方法进行优化
完整实现代码如下:
private static void mergeSortOP(int[] array,int left,int right,int[] temp){
if (right-left<16) { //没必要一直划分数据到1
inserSort(array, left, right);
}else {
int mid=left+((right-left)>>1);
// 1.划分数据
// [left,mid)--->左半部分
mergeSort(array,left,mid,temp);
// [mid,right)--->右半部分
mergeSort(array,mid,right,temp);
// 2.归并数据
mergeData(array,left,mid,right,temp);
// 因为归并好的数据存储在临时空间temp中
// 3. 将temp中的数据拷贝到array中去
System.arraycopy(temp,left,array,left,right-left);
}
}
// 合并数据 [left,mid) [mid,right)
private static void mergeData(int[] array,int left,int mid,int right,int[] temp){
int index=left;
int begin1=left,end1=mid,begin2=mid,end2=right;
while (begin1<end1 && begin2<end2){
if (array[begin1] <= array[begin2]) {
temp[index++]=array[begin1++];
}
else {
temp[index++]=array[begin2++];
}
}
// 如果第一个区间中还有数据
while (begin1<end1){
temp[index++]=array[begin1++];
}
// 如果第二个区间有数据
while (begin2<end2){
temp[index++]=array[begin2++];
}
}
// 插入排序
public static void inserSort(int[] array, int left, int right) {
for (int i = 1; i < array.length; ++i) {
int key = array[i];
int end = i - 1;
// 待插入元素在前面已排好序部分的位置
while (end >= 0 && key < array[end]) {
array[end + 1] = array[end];
end--;
}
//2.插入元素
array[end + 1] = key;
}
}
public static void printArray(int[] array) {
for (int e : array) {
System.out.print(e + " ");
}
}
public static void main(String[] args) {
int[] array={3,8,9,4,1,5,2,0,6,7};
mergeSortOP(array);
printArray(array);
}
}