四 归并排序
归并:把若干个有序的数列, 合成一个有序的数列
如二路归并:
void merge(int d1[], int len1, int d2[], int len2, int tmp[])
{
int i, j, k;
i = j = k = 0;
while (i < len1 && j < len2) {
if (d1[i] < d2[j])
tmp[k++] = d1[i++];
else
tmp[k++] = d2[j++];
}
while (i < len1)
tmp[k++] = d1[i++];
while (j < len2)
tmp[k++] = d2[j++];
}
1, 二路归并排序
迭代法:
把待排数列(长度为len)中的每个元素看作一个有序数列,两两归并, 再以相邻的两个元素为一个有序数列,两两归并,重复以上步骤,直到有序数列的长度大于或等于len。
void merge(int d1[], int len1, int d2[], int len2, int d[])
{
int i, j, k;
int tmp[len1 + len2];
i = j = k = 0;
while (i < len1 && j < len2) {
if (d1[i] < d2[j])
tmp[k++] = d1[i++];
else
tmp[k++] = d2[j++];
}
while (i < len1)
tmp[k++] = d1[i++];
while (j < len2)
tmp[k++] = d2[j++];
for (i = 0; i < k; i++) // k 改为k-1可以吗? 不可以!k是从0开始,且tmp[k-1]有值
d[i] = tmp[i];
}
void merge_sort(int d[], int len)
{
int i; //遍历数列
int gap = 1; //合并前一组数列的长度
while (gap < len) {
for (i = 0; i < len - 2 * gap; i = i + 2 * gap)
merge(d + i, gap, d + i + gap, gap, d + i);
if (len - i > gap)
merge(d + i, gap, d + i + gap, len - i - gap, d + i);
gap = gap * 2;
}
}
递归法:
把前后两个有序序列“归并”成一个有序序列
前、后两个有序序列,又由“归并排序(递归)”得来!
(递归法)由整个有序往前推理(往无序的方向推理,也是初始的方向)(由“果”到“因”,所以应用递归算法时,可以把结果看作已经实现)!
(迭代法)由无序往有序的方向推理(由“因”到“果”)
void merge_rec_sort(int d[], int len)
{
if (len <= 1)
return ;
merge_rec_sort(d, len / 2);
merge_rec_sort(d + len / 2, len - len / 2);
merge(d, len / 2, d + len / 2, len - len / 2, d);
}
注:归并排序是稳定的排序
时间复杂度最好最坏都为O(nlgn)