void merge (int* a, int n, int temp, int m);
void divideSort (int *a, int n, int m)
{
if (n < m)
{
int temp = (n + m) / 2;
divideSort (a, n, temp);
divideSort (a, temp + 1, m); //分解 解决 分解到叶子节点的时候已经解决了
merge (a, n, temp, m); //合并
}
}
void merge (int *a, int n, int temp, int m)
{
int i, j, nl, ml;
int *b, *c;
nl = temp - n + 1;
ml = m - temp;
if ((b = (int *) malloc (sizeof (int) * nl)) == NULL)
exit (0);
if ((c = (int *) malloc (sizeof (int) * m1)) == NULL)
{
free (b);
exit (0);
}
for (i = 0; i != nl; i++)
b[i] = *(a + n + i);
for (i = 0; i != ml; i++)
c[i] = *(a + temp + i + 1);
int x = 0, y = 0;
for (i = n; i <= m; i++)
{
if (b[x] > c[y])
{
*(a + i) = c[y++];
if (y > ml)
break;
}
else
{
*(a + i) = b[x++];
if (x > nl)
break;
}
}
int len = (x > nl) ? ml - y : nl - x;
if (x > nl)
for (j = 0; j < len; j++)
*(a + i++) = c[y++];
if (y > ml)
for (j = 0; j < len; j++)
*(a + i++) = b[x++];
free (b);
free (c);
}
归并排序有2个核心思想:
1.已经排好序的2个数组,他们合并成一个有序的数组用的时间复杂度时n(上面的merge)
2.通过分治的思想把原来的一个数组细分到叶子节点,然后回归
在temp = (n + m) / 2 可以可以看出它是一个2叉树,通过一步步的递归最后到达叶子节点,然后调用merge函数进行归并
递归一个2叉树需要logn + 1层,每一层的代价都是cn 那么 时间复杂度就是nlogn 了
在数量小的时候
1.分解:将N个数分成各含 n / 2个数的子序列
2.解决:用归并算法对2个子序列进行排序
3.合并:合并2个已经排序的子序列的到排序结果
虽然归并排序的时间复杂度要比插入排序小, 但是对于在数目很小的时候,插入排序的速度还是要快的(二次函数与一次函数的交点)
所以可以通过将归并的最小子序列长度设为k ,而在k个数的排序时,插入排序要来的快,于是就可以将插入排序和归并排序结合起来
void merge (int* a, int n, int temp, int m);
void insertSort (int *a, int length)
{
int i, j, temp;
for (j = 1; j < length; j++)
{
temp = *(a + j);
i = j - 1;
while (i >= 0 && *(a + i) > temp)
{
*(a + i + 1) = *(a + i);
i--;
}
*(a + i + 1) = temp;
}
}
void divideSort (int *a, int n, int m, int k)
{
if (m - n >= k)
{
int temp = (n + m) / 2;
divideSort (a, n, temp, k);
insertSort (a + n, temp - n + 1);
divideSort (a, temp + 1, m, k);
insertSort (a + temp + 1, m - temp);
merge (a, n, temp, m);
}
}
void merge (int *a, int n, int temp, int m)
{
int i, j, nl, ml;
int *b, *c;
nl = temp - n + 1;
ml = m - temp;
if ((b = (int *) malloc (sizeof (int) * nl)) == NULL
|| (c = (int *) malloc (sizeof (int) * ml)) == NULL)
exit (0);
for (i = 0; i != nl; i++)
b[i] = *(a + n + i);
for (i = 0; i != ml; i++)
c[i] = *(a + temp + i + 1);
int x = 0, y = 0;
for (i = n; i <= m; i++)
{
if (b[x] > c[y])
{
*(a + i) = c[y++];
if (y > ml)
break;
}
else
{
*(a + i) = b[x++];
if (x > nl)
break;
}
}
int len = (x > nl) ? ml - y : nl - x;
if (x > nl)
for (j = 0; j < len; j++)
*(a + i++) = c[y++];
if (y > ml)
for (j = 0; j < len; j++)
*(a + i++) = b[x++];
}