归并排序
1. 基本思想
基本流程:
-
确定分界点
-
递归排序
left
,right
-
归并——合二为一(重点)
2. 实现方法
-
双路归并,合二为一
-
时间复杂度为
o(n)
算法思想:
-
先把左边排好序,再把右边排好序
-
用
i
,j
分别指向数组1和数组2 -
比较
i
,j
指向的数据,若i
中的数据小于j
中的数据,则将i
中的数据取出放到tmp[]
数组中,i++
-
继续比较,直到某一指针指向其所对应的数组末尾,则将另一指针后面的所有的数直接拿到
tmp[]
数组的末尾 -
再将
tmp[]
数组中的数放回至想要存放数据的数组中
算法模板:
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
/*
自己第一遍写写成这样了,多了一些if这种很没必要的判断
if (i == mid+1)
while(j <= r) tmp[k++] = q[j++];
else if (j == r+1)
while(i <= mid) tmp[k++] = q[i++];
*/
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
个人觉得可以将k从l起开始赋值,写成以下形式,最后一步for循环的赋值或许会更简便一点
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = l, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l; i <= r; ++i) q[i] = tmp[i];
}