排序算法总结(四)归并排序

访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。

归并排序的核心就是合并两个有序数组,生成一个有序的新数组。在一个数组中如果数字都无序,那么把这个数组拆成两个或四个数组,拆成的小数组都不能保证有序,如果继续拆下去,如果数组有n个元素,那么就拆成n个数组,这时每个数组只包含一个元素,这个单元素数组就是有序的了,然后把这些单元素数组两两合并,如果n是双数,那么正好两个配对,完成合并,如果n是单数,那么最后一个元素之前的正好两个配对,最后一个元素与之前合并好有序数组再合并,这样全部元素都合并成了有序数组。

我们来看合并两个有序数组的算法。算法原理很简单,在这里使用一个辅助数组c,两个有序数组分别叫做a和b,都设置一个指针指向首元素,首先a和b的首个元素进行比较,小的元素放到c数组的第一个元素,比较中第一个元素小的数组指针前进一个元素,这个元素又成了首元素,这样一直比较下去,小的元素放到c数组,指针往前移一个元素,直到两个数组中有一个指针移到了尾部,这时把没有移到尾部的数组剩余的元素依次放入c数组,这样c数组中的元素就都是有序的了。

在实际的应用中,往往a和b两个数组是一个大数组前后两部分,这时a和b是连在一起的,比如大数组有8个元素1,3,5,7,2,4,6,8,拆分成a和b两个数组,a的元素为1,3,5,7,b的元素为2,4,6,8,其实a就是大数组的首地址。所以上面的c数组中的元素要拷贝回a数组中,便于后面更大的有序数组合并。

合并函数如下。

/* ai是要合并的两个数组首地址

* left是数组首元素下标,right是数组最后元素下标,mid是数组中间元素下标

* 两个数组中的元素分别是left到mid,mid+1到right,这两个数组元素都是有序的

* 比如ai={1, 3, 5, 7, 2, 4, 6, 8}, left=0, mid=3, mid+1=4,right=7

* left到mid的元素是1, 3, 5, 7

* mid+1到right的元素是2, 4, 6, 8

* tmp是辅助临时数组地址

*/

void merge(int *ai, int *tmp, int left, int mid, int right)

{

int i, j, k;

/* i是左边数组的指针,j是右边数组的指针,

* 从头开始比较,较小的元素放入辅助数组tmp中

* 任何一个数组到达尾部,退出循环

*/

for (i=left, j=mid+1, k=0; (i<=mid) && (j<=right); ) {

if (ai[i] < ai[j])

tmp[k++] = ai[i++];

else

tmp[k++] = ai[j++];

}

/* 左边的数组没比较完,把左边剩余的元素放入辅助数组 */

while (i <= mid)

tmp[k++] = ai[i++];

/* 右边的数组没比较完,把右边剩余的元素放入辅助数组 */

while (j <= right)

tmp[k++] = ai[j++];

/* 把辅助数组中的元素拷贝回原始数组中 */

for (i=0, j=left; j<=right; j++, i++)

ai[j] = tmp[i];

}

把数组中的每个元素拆分成单元素的数组,是在排序函数中完成的,使用递归的方式。函数如下。

/* ai是要排序的数组

* left是数组第一个元素的下标,right是数组最后一个元素的下标

* tmp是一个与ai大小相同的辅助数组

*/

void merge_sort(int *ai, int *tmp, int left, int right)

{

int mid;

/* 左边的下标值与右边的相等了,

* 表示数组中只有一个元素了,不要再拆分了

*/

if (left >= right)

return;

/* 得到中间值 */

mid = (left + right) / 2;

/* 一直拆分左边的数组,直到每个数组包含一个元素

* 这儿是递归调用,其实是每次到了这儿,又会调用自己把自己拆分成左右两个数组

* 直到最后是单元素数组时,函数返回,这时又把小数组逐渐合并成大数组

* 左半部分合并成有序的大数组后,才会继续下面的函数,又是拆分再合并的过程

*/

merge_sort(ai, tmp, left, mid);

/* 一直拆分右边的数组,直到每个数组包含一个元素 */

merge_sort(ai, tmp, mid+1, right);

/* 合并两个有序的数组,从小到大,直到合并成一个有序的大数组 */

merge(ai, tmp, left, mid, right);

}

相关推荐
几点才到啊2 小时前
使用 malloc 函数模拟开辟一个 3x5 的整型二维数组
数据结构·算法
<但凡.5 小时前
C++修炼:list模拟实现
开发语言·数据结构·c++
敲代码的瓦龙6 小时前
C++?动态内存管理!!!
c语言·开发语言·数据结构·c++·后端
Ronin3056 小时前
【C++】13.list的模拟实现
开发语言·数据结构·c++·list
序属秋秋秋7 小时前
《数据结构初阶》【顺序表 + 单链表 + 双向链表】
c语言·数据结构·笔记·链表
无敌的牛8 小时前
AVL树的介绍与学习
数据结构·学习
想不明白的过度思考者8 小时前
初识数据结构——二叉树从基础概念到实践应用
数据结构·二叉树
Brookty9 小时前
【数据结构】哈希表
数据结构·算法·哈希算法·散列表
Dovis(誓平步青云)11 小时前
【数据结构】·励志大厂版(复习+刷题):二叉树
c语言·数据结构·经验分享·笔记·学习·算法·学习方法
越城11 小时前
算法效率的钥匙:从大O看复杂度计算 —— C语言数据结构第一讲
c语言·开发语言·数据结构·算法