网站首页 > java教程 正文
写文章
归并排序原理
归并排序的核心思想是:利用分治策略,不断划分子序列直到不能划分为止,此时各个子序列是有序的,合并相邻有序子序列最终得到一个有序序列。我们利用下图解释划分子序列过程。
现在有原始序列[5, 10, 6, 8, 15, 11, 10, 7]采用递归的方式不断对序列进行划分,最终划分成单个元素的序列。有序子序列合并过程如下图所示:
相邻有序子序列进行合并,得到一个有序的序列。最终所有有序子序列进行合并得到一个完整的有序序列。
归并排序实现
根据子序列合并过程图我们可以看出,本质上就是两个有序子序列进行合并成一个有序序列的过程。划分的过程还是在原始序列里进行划分,所以相邻的序列必定有边界进行划分,现假设两个相邻子序列边界分别是left、mid和right。其中left~mid构成一个子序列,mid+1~right构成另外一个子序列,两个序列相邻。合并代码如下:
static void merge(data_type_t *src, int left, int mid, int right, data_type_t *temp){
if(src == NULL || temp == NULL){
return;
}
int i = left, j = mid + 1;
int index = 0;
while(i <= mid && j <= right){
if(src[i] < src[j]){
temp[index++] = src[i++];
}else{
temp[index++] = src[j++];
}
}
if(i <= mid){
//将剩余左边部分拷贝到临时缓冲区
memcpy(&temp[index], &src[i], (mid - i + 1) * sizeof(data_type_t));
}
if(j <= right){
//将右边剩余部分拷贝到临时缓冲区
memcpy(&temp[index], &src[j], (right - j + 1) * sizeof(data_type_t));
}
//将临时缓冲区的内容拷贝到原始缓冲区中
memcpy(&src[left], temp, (right - left + 1) * sizeof(data_type_t));
for(i = left; i <= right; i++){
printf("%d ", src[i]);
}
printf("\n");
}
每次将较小的值放在临时缓冲区中,其中一个子序列遍历完毕则退出循环,判断两个子序列是否都已遍历完毕,将未遍历完毕的子序列拷贝到临时缓冲区中,最后将临时缓冲区里的内容再复制到两个子序列的所在区间,这样两个子序列合并完毕且有序,为了便于观察合并过程,每进行一次归并则打印归并后的序列值。
归并排序实现代码如下:
void merge_sort(data_type_t *src, int left, int right, data_type_t *temp){
if(src == NULL || temp == NULL || left >= right){
return;
}
int mid = (left + right) / 2;
merge_sort(src, left, mid, temp);
merge_sort(src, mid + 1, right, temp);
merge(src, left, mid, right, temp);
}
在代码里我们递归对左边区域进行划分,然后再递归对右边区域进行划分,不断进行有序子序列合并。
归并排序算法验证
下面我们写一个小程序验证算法的正确性。
#include <stdio.h>
#include "merge_sort.h"
int main() {
data_type_t arr[8] = {5, 10, 6, 8, 15, 11, 10, 7};
data_type_t temp[8] = {0};
merge_sort(arr, 0, 7, temp);
printf("归并排序结果\n");
int i = 0;
for(i = 0; i < 8; i++){
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
为了便于观察,原始数据和图解的一样,现编译运行输出如下:
5 10
6 8
5 6 8 10
11 15
7 10
7 10 11 15
5 6 7 8 10 10 11 15
归并排序结果
5 6 7 8 10 10 11 15
从输出结果中,我们对照图解归并排序过程,完全符合。
- 上一篇: 看动图学算法(七):归并排序的原理和Java讲解
- 下一篇: 数据结构与算法之归并排序
猜你喜欢
- 2025-05-27 2025-04-29:高度互不相同的最大塔高和。用go语言,给定一个数组
- 2025-05-27 PHP排序算法:计数、选择、插入、归并、快速、冒泡、希尔、堆
- 2025-05-27 Python高级排序算法应用
- 2025-05-27 用好RANK函数 跨表排名不用愁
- 2025-05-27 十大排序算法时空复杂度
- 2025-05-27 Excel表格通过拆分再合并的方法对合并单元格排序
- 2025-05-27 万能的vlookup,居然能用来合并同类项,这个公式设计的太巧妙了
- 2025-05-27 算法基础:插入排序 实现原理和应用场景
- 2025-05-27 算法之常见排序算法-冒泡排序、归并排序、快速排序
- 2025-05-27 公式很短,将 Excel 合并单元格中的数据行按大小排序
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)