最近有点忙,所以有几天没更新,今天接上。
这次是归并算法,这个算法我的理解是属于一种化整为零的思路,即把一个序列一分为二,然后依次对拆分开的两个序列继续拆分,以此类推,直至每个序列只剩一个元素,然后再对每一段进行合并成一个有序序列的过程,就是一个拆分整合的过程。本次我使用递归的方法实现的,话不多说,直接上代码:
/*********** 归并排序 ***********/
/******** 千万注意边界条件 ********/
int Merge(double *SR, double *TR, int i, int m, int n, int arrMaxLenth)
{
int j, k, e;
for (j = m+1 , k = i ; i <= m && j <= n ; k++)
{
if (SR[i] > SR[j] && j < arrMaxLenth) // 注意边界条件
TR[k] = SR[j++];
else
TR[k] = SR[i++];
}
if (i <= m) // 前半段有多余的直接加到后面
{
for (e = 0 ; e <= m - i ; e++, k++)
TR[k] = SR[i + e];
}
if (j <= n && j < arrMaxLenth) // 后半段有多余的直接加到后面,注意边界条件
{
for (e = 0 ; e <= n - j ; e++, k++)
TR[k] = SR[j + e];
}
return 0;
}
int MSort(double *SR, double *TR1, int s, int t, int arrMaxLenth)
{
int m;
if (s == t && t < arrMaxLenth) // 注意边界条件
TR1[s] = SR[s];
else if(t > s)
{
double *TR2 = new double[t+1]; // 申请一段内存
m = (s + t) / 2;
MSort(SR, TR2, s, m, arrMaxLenth);
MSort(SR, TR2, m + 1, t, arrMaxLenth);
Merge(TR2, TR1, s, m, t, arrMaxLenth);
delete[] TR2; // 释放申请的内存
}
return 0;
}
int MergeSort(double *arr, int arrLenth)
{
double *TR = new double[arrLenth]; // 临时申请一段内存来存放数组
MSort(arr, TR, 0, arrLenth, arrLenth);
// 将TR数组里的还回arr中
int i;
for (i = 0; i < arrLenth; i++)
{
arr[i] = TR[i];
}
delete[] TR; // 释放申请的内存
return 0;
}
(这里提醒一下:千万注意申请的内存要及时释放掉,还有注意边界条件)
这其中 MSort 中主要为实现拆分,Merge 为实现合并,整体逻辑比较清晰。里面几处都申请了长串内存,而且还频繁申请内存,递归实现的归并排序,是比较耗性能和占用内存的,当然还是有优化的空间的,比如用参数传入,代替申请内存,就不会大量浪费内存损耗性能了,这里暂且不深讨论了。下一篇我们就用迭代的方法实现归并排序,迭代还是会比递归稍微更节省空间和时间。