介绍
归并排序(Merge Sort)是一种高效的排序算法,它将一个大的有序序列,通过递归的方式,分割成多个小的有序序列,然后将这些小序列合并在一起,得到一个完整的有序序列。
归并排序的主要思想是分治法,将一个大的问题分解成多个子问题来解决。具体步骤如下:
-
分解:将待排序的序列分成两半,递归地排序这两半。
-
合并:将两个有序的序列合并成一个有序的序列。
代码实现
#define PTR_MATH(base,i,width) ( ((char*)base) + (i)*width )
这是一个C语言的宏定义,用于实现指针的数学运算。它的目的是简化指针的偏移量计算,提高代码的可读性和可维护性。这个宏定义的实现原理是,通过将指针与一个整数相加,实现指针的偏移量计算。其中,base 是原始指针,i 是偏移量,width 是指针宽度。
//归并排序
void mergeSortRecursive(void* base, int begin, int end ,int width, int(*compare)(const void* e1, const void* e2),void* temp){
//递归终止条件
if(begin>=end-1)
return;
int mid = (begin+end)/2;
//递归调用
mergeSortRecursive(base,begin,mid,width,compare,temp);
mergeSortRecursive(base,mid,end,width,compare,temp);
//当前合并位置的下标
int index_1 = begin, index_2 = mid;
//将前后两段分别有序的数据合并
int index;
for(index =begin;index_1<mid && index_2<end;index++){
if(compare(PTR_MATH(base,index_1,width),PTR_MATH(base,index_2,width))<=0){
memcpy(PTR_MATH(temp,index,width),PTR_MATH(base,index_1,width),width);
index_1++;
}else{
memcpy(PTR_MATH(temp,index,width),PTR_MATH(base,index_2,width),width);
index_2++;
}
}
//将剩余数据合并
if(index_1<mid){
memcpy(PTR_MATH(temp,index,width),PTR_MATH(base,index_1,width),(mid-index_1)*width);
}else{
memcpy(PTR_MATH(temp,index,width),PTR_MATH(base,index_2,width),(end-index_2)*width);
}
//将合并后的数据复制回原数组
memcpy(PTR_MATH(base,begin,width),PTR_MATH(temp,begin,width),width*(end-begin));
}
void mergeSort(void* base, int len,int width, int(*compare)(const void* e1, const void* e2)){
if(base==NULL||compare == NULL||width<=0||len<=1)
return;
void * temp = malloc(width*len);
if(temp == NULL)
return;
mergeSortRecursive(base,0,len,width,compare,temp);
free(temp);
}
1.mergeSortRecursive
函数:
这个函数是归并排序的递归实现。它接受以下参数:
base
:原始数组的起始地址。begin
:当前合并范围的起始下标。end
:当前合并范围的结束下标。width
:数组中每个元素的大小。compare
:一个比较函数,用于比较两个元素的大小。temp
:一个临时数组,用于存储合并后的数据。
函数首先检查递归终止条件,如果当前合并范围的长度小于等于1,则直接返回。否则,将当前合并范围分成两半,递归地对每一半进行排序,然后将两个有序数组合并成一个有序数组。
2.mergeSort
函数:
这个函数是归并排序的接口函数。它接受以下参数:
base
:原始数组的起始地址。len
:数组的长度。width
:数组中每个元素的大小。compare
:一个比较函数,用于比较两个元素的大小。
函数首先检查输入参数是否合法,如果不合法,则直接返回。然后,为临时数组分配内存,并调用 mergeSortRecursive
函数进行排序。最后,释放临时数组的内存。
图解
总结
归并排序的时间复杂度为O(n log n),空间复杂度为O(n)。它是一种稳定的排序算法,适用于大规模的数据排序。