通过将数组分为两组及以上,在分组进行排序,最后将排序好的分组进行整合,通过比较两数组的最大和最小值来进行比较,即数组1的最大元素和数组2最小元素进行比较,若不成立,则反过来进行对比,然后便逐一排序分组,(ps:自己理解)
归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
归并排序算法稳定,数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n)),算法不是自适应的,不需要对数据的随机读取。
工作原理:
1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2、设定两个指针,最初位置分别为两个已经排序序列的起始位置
3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4、重复步骤3直到某一指针达到序列尾
5、将另一序列剩下的所有元素直接复制到合并序列尾。
代码如下:
package com.qdcz.breadth.demo;
/**
*
* <p>Title: MergeA</p>
* <p>Description:归并排序算法实现类 </p>
* <p>Company: 奇点创智</p>
* <p>Version: 1.0</p>
* @author Administrator
* @date 2017年6月6日 下午4:52:30
*/
public class MergeA {
public static void main(String[] args) {
int[] data ={23,3,5,4,2,54,24,55};
print(data);
mergeSort(data);
System.out.println("排序后的数组:");
print(data);
}
/**
*
*<p>Title: mergeSort</p>
*<p>Description:给定 数组左右索引</p>
*@param data
*@return void
*@author Administrator
*@date 2017年6月6日 下午5:10:01
*/
public static void mergeSort(int [] data){
sort(data,0,data.length-1);
}
/**
*
*<p>Title:print </p>
*<p>Description:,对整数组分开并进行递归 </p>
*@param data
*@param left
*@param right
*@return void
*@author Administrator
*@date 2017年6月6日 下午5:07:43
*/
private static void sort(int[] data, int left, int right) {
if(left>=right) return;
int center=(left+right)/2;
sort(data,left,center);
sort(data,center+1,right);
merge(data,left,center,right);
print(data);
}
/**
*
*<p>Title: print</p>
*<p>Description: 对数组进行输出</p>
*@param data
*@return void
*@author Administrator
*@date 2017年6月6日 下午5:07:14
*/
private static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+"\t");
}
System.out.println();
}
/**
*
*<p>Title: merge</p>
*<p>Description: 归并排序算法核心方法,将两个分开数组合并</p>
*@param data
*@param left 左数组第一个
*@param center 全数组中心索引
*@param right 右数组最后一个元素索引
*@return void
*@author Administrator
*@date 2017年6月6日 下午5:04:18
*/
private static void merge(int[] data, int left, int center, int right) {
int[] temp=new int[data.length];//建立新的数组
int mid=center+1;// 右数组第一个元素索引
int thrid=left;// third 记录临时数组的索引
int tmp=left;// 缓存左数组第一个元素的索引
while(left<=center&&mid<=right){
// 从两个数组中取出最小的放入临时数组
if(data[left]<=data[mid]){
temp[thrid++]=data[left++];
}else{
temp[thrid++]=data[mid++];
}
}
// 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
while(mid<=right){
temp[thrid++]=data[mid++];
}
while(left<=center){
temp[thrid++]=data[left++];
}
//将临时数组中的内容拷贝回原数组中
// (原left-right范围的内容被复制回原数组)
while(tmp<=right){
data[tmp]=temp[tmp++];
}
}
}