【3】归并排序
原理:分为三部分:
1.新建辅助数组
2.先递归分解原数组,不断分成两部分循环递归排序
3.合并数组,同时把合并排序后的元素放到辅助数组中
1.新建辅助数组
2.先递归分解原数组,不断分成两部分循环递归排序
3.合并数组,同时把合并排序后的元素放到辅助数组中
时间复杂度:O(nlogn)
稳定
缺点:需要额外的N空间来进行排序
和快排一样的复杂度,但是稳定排序,排序关键字相等的两个元素在整个序列排序的前后,相对位置不会发生变化。因此是稳定性排序中效率最高的一个,c++\python等稳定性排序的内部实现中,都是使用的归并排序。
Java实现
package com.hello.kitty.sort;
/**
* @name: S_04_MergeSort.class
* @Author :
* @create : 2020-01-11
* @Desc: 归并排序
* 思路:1,分:分别归并排序左右两块
* 2.合并左右两块
* 如果右指针>右边界,说明剩下的数都在左边,直接加,因为已排序
* 左指针>mid,说明剩下的数都在右边,直接加,因为已排序
* 之后就是判断大小,谁小加谁
* 优缺点:效率高、稳定、O(nlogn),但是需要额外的辅助空间
*/
public class S_04_MergeSort {
public static int[] mergeSort(int[]arr, int[] tmpArr,int left, int right){
if(left < right){
int mid = (left + right)/2;
//归并排序左半部分
mergeSort(arr,tmpArr, left,mid);
//归并排序右半部分
mergeSort(arr,tmpArr,mid+1, right);
//合并左右两块
merge(arr, tmpArr,left, mid+1, right);
}
return null;
}
/**
* 合并两个有序数组
* @param arr
* @param tmpArr
* @param left
* @param mid
* @param right
* @return
*/
public static int[] merge(int[]arr, int[] tmpArr,int left, int mid,int right){
int i = left;
int j = mid+1;
//先把元素放进辅助数组
for(int k = left;k<right;k++){
tmpArr[k] = arr[k];
}
for(int k = left;k<right;k++){
//两块比较,i是第一块的指针,j是第二快的指针
//左边排完了,说明剩下的大数都在右半部分
if(i>mid){
arr[k] = tmpArr[j++];
}else if(j > right){
//右边排完了,说明大数在左半部分
arr[k] = tmpArr[i++];
}else if(tmpArr[i] < tmpArr[j]){
//否则,左边小,取左边
arr[k] = tmpArr[i++];
}else{
//右边小,取右边
arr[k] = tmpArr[j++];
}
}
return null;
}
public static void main(String[] args) {
int[] arr = {3,1,4,2,8,6,5,4};
int[] tmpArr = new int[8];
mergeSort(arr, tmpArr, 0, 7);
}
}
/**********************************************************
名称:归并排序
原理:分为三部分:
1.新建辅助数组
2.先递归分解原数组,不断分成两部分
3.合并数组,同时把合并排序后的元素放到辅助数组中
***********************************************************/
#include "stdafx.h"
#include<iostream>
using namespace std;
void Merge(int a[],int first,int mid,int last,int atmp[])
{
int i = first,j = mid + 1;
//把元素拷贝到辅助数组中
for(int k = first; k <= last; k++)
{
atmp[k] = a[k];
}
//之后按照排序从辅助数组中拷贝回原数组
for(int k = first; k <= last; k++)
{
if(i > mid)//一块的头大于中点,说明左边镁元素了
{
a[k] = atmp[j++];
}
else if(j > last)//一块的尾超过终点,说明右边没元素
{
a[k] = atmp[i++];
}
else if(atmp[i]<atmp[j])//两块的头尾都在序列中,左边元素小,则入队,然后从下一个开始继续比
{
a[k] = atmp[i++];
}
else
{
a[k] = atmp[j++];
}
}
}
void mergesort(int a[],int first,int last,int atmp[])//把数组递归划分排序,再合并
{
if(first < last)
{
int mid = (first + last)/2;//平分数组,找到中间值
mergesort(a,first,mid,atmp);//循环对左边排序
mergesort(a,mid+1,last,atmp);//循环对右边排序
Merge(a,first,mid,last,atmp);//将两个有序序列合并
}
}
void MergeSort(int a[],int length)//归并排序函数
{
int *atmp = new int[length];//新建辅助数组
mergesort(a,0,length-1,atmp);
delete [] atmp;
for(int i = 0;i!=length;i++)
{
cout << a[i]<<" ";
}
}
int main()
{
int length = 0;
int i = 0;
cout << "请输入排序数组长度:" << endl;
cin >> length;
int a[100] = {0};
cout << "请输入排序数组:" << endl;
for(;i!=length;i++)
cin>>a[i];
cout << "归并排序:" << endl;
MergeSort(a,length);
cout << endl;
system("pause");
return 0;
}
参考资料:http://www.cnblogs.com/yangecnu/p/Introduce-Merge-Sort.html