内容:
- 归并排序算法思想
- 归并排序算法的实现
- 归并排序算法的优化
1、归并排序算法思想
对于给定的一串数组如:5、3、7、2、6、4、8、1
我们可以进行如下几个步骤:
- 将数组从中间分成两组数组——>5、3、7、2和6、4、8、1分别排序;
- 同样,我们可以继续拆分这两个数组为5、3和7、2以及6、4和8、1分别排序;
- 我们将想要排序的数组拆分再排序,就会形成循环,直到不能拆分为止。
- 排序完成后,再将排序完成后的数组合并。
分治法:将一个大的问题,分成若干个小的问题来处理,再将结果合并。
递归:在循环过程中,我们不断拆分数组本身,即不断调用递归函数。
递归到底:数组的长度是有限的,不断拆分后,数组就会拆分为只有一个元素时,数组就会无法拆分,递归结束。
算法分析:
2-路归并排序
两路归并:就是将两个有序表合并成一个有序表。即上述排序完成后,进行合并操作。
内容:对于数组我们给定三个指标:数组第一个元素first,中间元素mid,最后一个元素last。传入数组到函数是,我们就调用函数继续将[first,mid]和[mid+1,last]传入函数,即循环拆分数组,直到递归到底。然后,对拆分后数组进行排序合并。即:
template<typename T>
void mergeSort(T arr[],int first,int last)
{
if (first >= last)//递归到底就结束
return;
int mid = (last + first) / 2;//取中间数,并向下取整
//注意:传入的数组并不变,是传入的索引(参数)在不断变化
mergeSort(arr,first,mid);//对左子序列进行归并排序
mergeSort(arr,mid+1,last);//对右子序列进行归并排序
merge(arr,first,mid,last);//归并
}
归并操作:——void merge(int arr[],int first,int mid,int last);
1)、对于两个数组合并,需要三个索引和一个辅助空间temp。即int i=first;用于访问第一个数组,int j=mid+1;用于访问第二个数组。k用来表示辅助空间temp的索引。
2)、同时,我们事先需要申明一块内存大小为last-first+1空间用来保存之前未拆分的数组(就是传入merge()函数的数组)即——
int *temp = new int[last - first + 1];//申请一块辅助空间用来保存传入函数的数组arr中的数据
for (int i = first;i <= last;i++)
{
temp[i - first] = arr[i];//将数组arr中i-first到last元素赋值给temp中,first为偏移量
}
3)、从头逐一比较两个数组([firsr,mid]和[mid+1,last])之间大小,较小者存入数组arr中,i走完[firsr,mid],j走完[mid+1,last]就完成了合并操作。
int i = first, j = mid + 1;//创建索引:i表示数组[first,mid]索引,j表示数组[mid+1,last]数组的索引
for (int k = first;k <=last;k++)//k指向数组中第一个元素
{
if (i > mid)//考虑到i越界
{
arr[k] = temp[j - first];
j++;
}
else if (j > last)//考虑到j越界
{
arr[k] = temp[i - first];
i++;
}
else if (temp[i - first] < temp[j - first])//注意:j是随着i相对变化的,偏移量也是first
{
arr[k] = temp[i - first];
i++;
}
else
{
arr[k] = temp[j-first];
j++;
}
}
或者这么写:
//将有二个有序数列a[first...mid]和a[mid...last]合并。
void mergearray(int a[], int first, int mid, int last, int temp[])
{
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0;
while (i <= m && j <= n)
{
if (a[i] <= a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i <= m)
temp[k++] = a[i++];
while (j <= n)
temp[k++] = a[j++];
for (i = 0; i < k; i++)
a[first + i] = temp[i];
}
2、归并排序算法的实现
#include<iostream>
using namespace std;
//归并排序
template<typename T>
void MergeSort(T arr[],int n)
{
mergeSort(arr,0,n-1);
}
template<typename T>
void mergeSort(T arr[],int first,int last)
{
if (first >= last)//递归到底就结束
return;
int mid = (last + first) / 2;//取中间数,并向下取整
//注意:传入的数组并不变,是传入的索引(参数)在不断变化
mergeSort(arr,first,mid);//对左子序列进行归并排序
mergeSort(arr,mid+1,last);//对右子序列进行归并排序
merge(arr,first,mid,last);//归并
}
template<typename T>
void merge(T arr[],int first,int mid,int last)
{
int *temp = new int[last - first + 1];//申请一块辅助空间用来保存传入函数的数组arr中的数据
for (int i = first;i <= last;i++)
{
temp[i - first] = arr[i];//将数组arr中i-first到last元素赋值给temp中,first为偏移量
}
int i = first, j = mid + 1;//创建索引:i表示数组[first,mid]索引,j表示数组[mid+1,last]数组的索引
for (int k = first;k <=last;k++)//k指向数组中第一个元素
{
if (i > mid)//考虑到i越界
{
arr[k] = temp[j - first];
j++;
}
else if (j > last)//考虑到j越界
{
arr[k] = temp[i - first];
i++;
}
else if (temp[i - first] < temp[j - first])//注意:j是随着i相对变化的,偏移量也是first
{
arr[k] = temp[i - first];
i++;
}
else
{
arr[k] = temp[j-first];
j++;
}
}
}
int main()
{
int a[] = { 3,8,4,7,2,1,5,6 };
int len = sizeof(a) / sizeof(a[0]);
cout << "排序前:";
for (int i = 0;i < len;i++)
cout << a[i] << " ";
cout << endl;
MergeSort(a,8);
cout << "排序后:";
for (int i = 0;i < len;i++)
cout << a[i] << " ";
cout << endl;
system("pause");
return 0;
}
精彩内容——>点击继续