1.基本思想
归并排序(MERGE–SORT)是建立在归并操作上的一种有效的排序算法该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并排序核心步骤(升序排序):
2.递归版–代码实现
升序排序
步骤:
比照函数,一步一步分析
- mid = 3
- left1 = 0, right1 = 3, left2 = 4 ,right2 = 7
- MergeSort(arr, a,0, 3)
- mid = 1
- left1 = 0, right1 = 1, left2 = 2 ,right2 = 3
- MergeSort(arr, a,0, 1)
- mid = 0
- left1 = 0, right1 = 0, left2 = 1 ,right2 = 1
- MergeSort(arr, a,0, 0)
- if (left >= right) return;
- MergeSort(arr, a, 1, 1)
- if (left >= right) return;
- i = 0
- 进入第一个 while 循环 ,arr[0]>arr[1] , a[0] = arr[1]
- left1 <= right1, a[1] = arr[0]
- memcpy
- MergeSort(arr, a,2, 3)
- …
//归并排序
void MergeSort(int* arr, int*a, int left, int right)
{
//结束条件
if (left >= right)
{
return;
}
int mid = (left + right) / 2;
//分两组
int left1 = left ,right1 = mid;
int left2 = mid + 1, right2 = right;
//调用自己
MergeSort(arr, a,left1, right1);
MergeSort(arr, a,left2, right2);
//排序
int i = left;
while (left1 <= right1 && left2 <= right2)
{
if ( arr[left1] < arr[left2])
{
a[i++] = arr[left1++];
}
else
{
a[i++] = arr[left2++];
}
}
//把没插入完的部分也插入进去
while (left1 <= right1)
{
a[i++] = arr[left1++];
}
while (left2 <= right2)
{
a[i++] = arr[left2++];
}
memcpy(arr + left, a+left, sizeof(int)*(right - left + 1));
}
int main()
{
int arr[] = {10,6,7,1,3,9,4,2};
//产生一个存放数组
int* a = (int*)malloc(sizeof(int) * (sizeof(arr) / sizeof(int)));
MergeSort(arr, a, 0, sizeof(arr) / sizeof(int)-1);
return 0;
}
3.非递归版–代码实现
(1)排序一段copy一段
递归函数是把数组分至为每组只有一个的数,把两组进行排序,接着排序进每组为只有2个的数…
改成非递归后,直接先进行一个一个数比较,在两个两个的比较…
代码演示:
//排序一部分后立即拷贝此部分
void MergeSortNoR_1(int* arr, int *a,int left, int right ,int n)
{
//先开始一组一个元数
int gap = 1;
while (gap <= n)
{
for (int i = 0; i < n; i+=gap*2)
{
int left1 = i, right1 = i + gap - 1;
int left2 = i + gap, right2 = i + gap * 2 - 1;
//越界处理
if (right1 > n || left2 > n)
{
break;
}
if (right2 > n)
{
right2 = n;
}
int j = i;
while (left1 <= right1 && left2 <= right2)
{
//判断大下
if (arr[left1] < arr[left2])
{
a[j++] = arr[left1++];
}
else
{
a[j++] = arr[left2++];
}
}
//没放完的继续放
while (left1 <= right1)
{
a[j++] = arr[left1++];
}
while (left2 <= right2)
{
a[j++] = arr[left2++];
}
//排序一部分就拷贝一部分
memcpy(arr + i, a + i, sizeof(int) *(right2-i+1) );
}
gap += gap;
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1 };
int* a = (int*)malloc(sizeof(int) * 9);
MergeSortNoR_1(arr, a, 0, 8, 8);
return 0;
}
(2)排序一遍后再拷贝
实录基本和上面的一样,越界处理不同
//排序一遍完后再拷贝
void MergeSortNoR_2(int* arr, int* a, int left, int right, int n)
{
//先开始一组一个元数
int gap = 1;
while (gap <= n)
{
for (int i = 0; i < n+1; i += gap * 2)
{
int left1 = i, right1 = i + gap - 1;
int left2 = i + gap, right2 = i + gap * 2 - 1;
//越界处理
if (right1 > n )
{
right1 = n;
left2 = n ;
right2 = n-1;
}
else if (left2 > n)
{
left2 = n ;
right2 = n-1;
}
else if (right2 > n)
{
right2 = n;
}
int j = i;
while (left1 <= right1 && left2 <= right2)
{
//判断大小
if (arr[left1] < arr[left2])
{
a[j++] = arr[left1++];
}
else
{
a[j++] = arr[left2++];
}
}
//没放完的继续放
while (left1 <= right1)
{
a[j++] = arr[left1++];
}
while (left2 <= right2)
{
a[j++] = arr[left2++];
}
}
//排序一遍后再拷贝
memcpy(arr, a, sizeof(int) * (n+1));
gap += gap;
}
return;
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1 };
int* a = (int*)malloc(sizeof(int) * 9);
MergeSortNoR_1(arr, a, 0, 8, 8);
return 0;
}