归并排序(合并排序)是将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序若将两个有序表合并成一个有序表,称为二路归并。
归并操作(合并),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。
给定一个初始数列:6,202,100,301,38,8,1
第一次归并后:{6 202},{100 301},{8.38},{1}
第二次归并后:{6 100 202 301},{1,8,38}
第三次归并后:{1,6,8,38,100,202,301}
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾,将另一序列剩下的所有元素直接复制到合并序列尾
void Merge(int *arr,int len,int gap)
{
int *brr = (int *)malloc(sizeof(int) * len);
assert(brr != NULL);
int i = 0;//brr的下标
int start1 = 0;
int end1 = start1+gap-1;
int start2 = end1+1;
int end2 = start2+gap-1 < len-1 ? start2+gap-1 : len-1;
//当有两个归并段的时候
while(start2 < len)
{
//当两个归并段还没有比较完的时候
while(start1 <= end1 && start2<=end2)
{
if(arr[start1] <= arr[start2])
{
brr[i++] = arr[start1++];
}
else
{
brr[i++] = arr[start2++];
}
}
while(start1 <= end1)
{
brr[i++] = arr[start1++];
}
while(start2 <= end2)
{
brr[i++] = arr[start2++];
}
//找两个新的归并段
start1 = end2+1;
end1 = start1+gap-1;
start2 = end1+1;
end2 = start2+gap-1 < len-1?start2+gap-1:len-1;
}
while(start1 < len)
{
brr[i++] = arr[start1++];
}
for(int i = 0;i < len;i++)
{
arr[i] = brr[i];
}
}
void MergeSort(int *arr,int len)
{
for(int i = 1;i < len;i *= 2)
{
Merge(arr,len,i);
}
}
void Show(int *arr,int len)
{
for(int i = 0;i < len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[6] = {6,202,100,301,38,8,1};
int len = sizeof(arr)/sizeof(arr[0]);
MergeSort(arr,len);
Show(arr,len);
return 0;
}