前面几篇内容,我们看了最基础的排序算法:冒泡排序,插入排序、选择排序。之所以说它们是基础的排序算法,是因为这几个排序算法的时间复杂度有点高,是O(n^2) ,适合于小规模的数据排序。
这一篇我们来看一个高效一点的算法,也就是今天的主角:归并排序,时间复杂度是O(nlogn)
#考考你:
1.你知道归并排序的核心思想吗?
2.你能用java实现归并排序吗?
案例
归并排序核心思想
假设有一个待排序序列:[4, 5, 6, 3, 2, 1]。我们需要按照升序进行排序,排序后的序列是这 样的:[1, 2, 3, 4, 5, 6]。
如何通过归并排序实现呢?
归并排序核心思想:
归并排序算法,利用分而治之思想,包含两个过程:分解、合并。
分解: 将一个大的待排序序列,分成两个小的待排序序列;再将小的待排序序列,继续分解成更小的待排序序列......一直到问题不能分解为止
合并: 将分解过程中层层分解后的小的待排序序列,再层层从小到大合并,在合并过程中实现排序......最终完成整个排序
用文字描述,稍微有点抽象,我们看一个图,你应该就明白了。
归并排序代码实现
入口函数
/**
* 归并排序入口
* @param array 待排序数组
* @param n 数据规模
*/
public static void sort(Integer[] array,int n){
// 如果数据规模小于等于1,直接返回
if(n <= 1){
return;
}
// 归并排序函数
mergeSort(array,0,n-1);
}
分解函数
/**
* 归并排序函数(递归实现)
* @param array 待排序数组
* @param left 数组起始下标
* @param right 数组结束下标
*/
public static void mergeSort(Integer[] array,int left,int right){
if(left >= right){
System.out.println("满足left>=right,退出递归: left="+left+",right="+right);
return;
}
// 求解中间下标
int mid = (left + right) / 2;
System.out.println("当次排序:left="+left+",right="+right+",mid="+mid);
// 分解后的左边待排序序列
mergeSort(array,left,mid);
// 分解后的右边待排序序列
mergeSort(array,mid+1,right);
// 合并函数
merge(array,left,mid+1,right);
}
合并函数
/**
* 合并函数
* @param array
* @param left
* @param mid
* @param right
*/
public static void merge(Integer[] array,int left,int mid,int right){
// 左边数组大小(临时数组)
int[] leftA = new int[mid-left];
// 右边数组大小(临时数组)
int[] rightA = new int[right-mid+1];
// 左边数组填充数据
for(int i=left;i<mid;i++){
leftA[i-left]=array[i];
}
// 右边数组填充数据
for(int j=mid;j<=right;j++){
rightA[j-mid]=array[j];
}
// 定义两个位置指针,标记左右数组,合并元素位置
int L_INDEX=0,R_INDEX=0;
// 当次合并,array数组中元素起始位置
int k=left;
// 比较两个数组的值,将小的一个元素
// 放入数组array中,实现排序
while(L_INDEX<leftA.length &&
R_INDEX<rightA.length){
// 谁比较小,谁将元素放入大数组中,移动指针,继续比较下一个
if(leftA[L_INDEX] <= rightA[R_INDEX]){
array[k++]=leftA[L_INDEX++];
}else{
array[k++] = rightA[R_INDEX++];
}
}
// 收尾工作:如果左边的数组有剩余元素,继续填充
while(L_INDEX<leftA.length){
array[k++] = leftA[L_INDEX++];
}
// 收尾工作:如果右边的数组有剩余元素,继续填充
while(R_INDEX<rightA.length){
array[k++] = rightA[R_INDEX++];
}
}
测试代码
public static void main(String[] args) {
// 初始化测试数组
Integer[] array = {4,5,6,1,2,3};
// 排序前
System.out.println("1.排序前数组:" + Arrays.deepToString(array));
// 2.排序
System.out.println("2.开始排序-------------------------------");
sort(array,array.length);
// 排序后
System.out.println("3.排序后数组:" + Arrays.deepToString(array));
}
讨论分享
#考考你答案:
1.你知道归并排序的核心思想吗?
1.1.归并排序,利用分治思想
1.2.有两个过程:分解、合并
1.3.分解过程:
将大的待排序序列,分解成小的待排序序列,层层分解,直到不能再分解为止
1.4.合并过程:
将分解后的小的待排序序列,从小到大,层层合并,在合并过程中实现排序
2.你能用java实现归并排序吗?
2.1.参考代码实现