八种排序的关系:
一、基本思想
归并排序将两个有序表合并·成一个新的有序表, 即把待排序的序列分成若干个子序列,每个序列都是有序的,然后将有序子序列合并成整体有序序列。
二、实例
三、实现过程解析
归并排序的核心经过两个分解, 合并,
分解: 由于合并中合并的序列必须为有序序列, 如何选择, 不断的惊醒分解, 分解到成一个元素的序列,那一定是一个有序的序列,这就要借助递归, 将一个源序列拆分成一个个有序的序列
然后就是进行合并。
3.1 、合并,将两个有序的序列合并成一个有序的序列
首先来看合并部分, 提供连个子序列, 设定为有序的
数组data[] 中
left … center
center … right
合并就是将者两个子序列进行合并。
创建一个临时数组用于存储这个序列的元素, 长度为两个子序列的长度:
int tmpArr = new int[right-left+1];
定义一个变量用于存储存到临时数组中的索引
int third = left;
定义一个变量作为第二个元素的索引记录
int tmp=left;
int mid = center+1;
因为两个子序列都是有序序列, 所以从两个序列中依次拿出元素比较, 小的元素存入临时数组中。
while(left<=center&&mid<=right){
//从两个数组中取出最小的放入中间数组
if(data[left]<=data[mid]){
tmpArr[third++]=data[left++];
}else{
tmpArr[third++]=data[mid++];
}
}
两个序列比较结束, 是以其中一个序列中元素比较完成, 并不知道另一个序列中元素是否比较完了,所以需要将序列中的剩余元素存入临时数组中
while(mid <=right) {
tmpArr[third++]=data[mid++];
}
while(left <= center) {
tmpArr[third++]=data[left++];
}
比较完成, 要将临时数组中的元素,存入原来的数组中
for(i=0; i<tmpArr.length; i++) {
data[tmp++]=tmpArr[i++];
}
3.2分解, 分治思想
在上面的示意图中, 可以看到, 不断将待排序的数组进行拆分,最终拆分一个元素,
定义center ,将序列分成两个子序列,
对两部分子序列各自进行排序,(由于这个排序递归执行) 最终拆分成一个个单独元素, 最后才调用merger() 进行合并。
/**
*
* @param data
* @param left
* @param right
*/
public void sort(int[] data, int left, int right) {
if(left<right){
//找出中间索引
int center=(left+right)/2;
//对左边数组进行递归
sort(data,left,center);
//对右边数组进行递归
sort(data,center+1,right);
//合并
merge(data,left,center,right);
}
}
四、java实现
package com.chb.sort;
import java.util.Arrays;
public class mergingSort {
int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};
public mergingSort(){
sort(a,0,a.length-1);
for(int i=0;i<a.length;i++)
System.out.println(a[i]);
}
/**
*
* @param data
* @param left
* @param right
*/
public void sort(int[] data, int left, int right) {
if(left<right){
//找出中间索引
int center=(left+right)/2;
//对左边数组进行递归
sort(data,left,center);
//对右边数组进行递归
sort(data,center+1,right);
//合并
merge(data,left,center,right);
}
}
/**
* 将两个序列合并
*
* @param data
* @param left
* @param center
* @param right
*/
public void merge(int[] data, int left, int center, int right) {
int [] tmpArr=new int[data.length];
int mid=center+1;
//third记录中间数组的索引
int third=left;
int tmp=left;
while(left<=center&&mid<=right){
//从两个数组中取出最小的放入中间数组
if(data[left]<=data[mid]){
tmpArr[third++]=data[left++];
}else{
tmpArr[third++]=data[mid++];
}
}
//剩余部分依次放入中间数组
while(mid<=right){
tmpArr[third++]=data[mid++];
}
while(left<=center){
tmpArr[third++]=data[left++];
}
//将中间数组中的内容复制回原数组
while(tmp<=right){
data[tmp]=tmpArr[tmp++];
}
System.out.println(Arrays.toString(data));
}
}