思想:
归并排序的核心是归并,即将两个有序数组合并成一个有序数组的操作。通过该方法加上分治的思想我们设计了归并排序,首先将一个数组划分为两个数组,由于这两个数组并未排好序,因此要继续划分,直至变成两个有序的数组(即长度为1),这时再逐级调用归并算法,不断将有序小数组归并成有序大数组。
自上而下&自下而上归并的区别:
自上而下:采用了分治的思想,因此每次划分的数组大小都是差不多一样大的,但是这会造成最后有很多长度为3的小数组,要进行划分。
自下而上:由于我们知道分治的最终结果是长度为1的小数组,那么就直接以长度为1的小数组为单位进行两两归并。不过这会造成最后归并的时候两个有序大数组的长度不一样。
复杂度:
时间复杂度:
O(nlgn)
O
(
n
l
g
n
)
因为单位数组(长度为一)的比较次数为lgn,这样的数组有n个,故需要0.5nlgn的比较次数。
空间复杂度: O(n) O ( n )
特点:
- 占额外空间
- 稳定排序
- 线性对数排序时间
- 自底向上适合于链表数组,因为不用新数组。
伪代码:
归并操作:谁小放谁。
merge(arr[], lo, mid, hi){
temp[lo->hi]=copyOf(arr[lo->hi]);
i=lo,j=mid+1;
for(index=lo->hi){
if(i>mid) arr[index]=temp[j++];
else if(j>hi) arr[index]=temp[i++];
else if(temp[i]<temp[j]) arr[index]=temp[i++];
else arr[index]=temp[j++];
}
}
分治操作(自顶向下):
sort(arr[], lo, hi){
if(lo>=hi) return;
sort(arr[], lo, mid);
sort(arr[], mid+1, hi);
merge(arr[], lo, mid, hi);
}
自底向上:
sort(arr[]){
for(step=2->N,step=2*step){
for(i=1->N-1,i=i+step){
merge(arr[], i, i+step-1, min(i+step*2-1, N-1));
}
}
}