关于算法--分治法--合并排序
分治法:
1、思想:①将问题的实例划分为同一个问题的几个较小的实例,最好拥有相同的规模;②对于较小的实例进行求解,一般使用递归法,在问题规模足够小的情况下也是用另一个算法;③如果必要的话,合并这些较小问题的解
2、通用分治递推式:T(n) = a*T(n/b) + f(n); 其中,T(n)是指运算次数
3、主定律:上式中的f(n)是属于Θ(nd),d≥0,则:
当a<bd时,T(n)属于Θ(nd);
当a=bd时,T(n)属于Θ(nd * log n);
当a>bd时,T(n)属于Θ(nlogba)
合并排序
一、步骤
a. 1、输入一个可排序数组arr,如果其规模大于1,则将其分为两个规模基本相同的子数组_arr1,_arr2
2、对子数组分别重新调用本函数
3、递归调用完毕后,调用b方法,对有序数组进行合并
b. 1、输入为两个有序数组arr1,arr2以及一个存储容器arr3
2、对arr1 arr2内的元素进行比对,小的赋值给arr3,并将大的与下一个比较
3、若其中有一个比较完毕,则将另外一个剩下的数字依次赋值到数组尾部
二、JavaScript代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>合并排序法</title>
</head>
<body>
</body>
<script type="text/javascript">
var mergesort = function(arr) {
var n = arr.length;
if (n > 1) {
//将数组平均分为两个子数组
var _arr1 = arr.slice(0, Math.floor(n/2));
var _arr2 = arr.slice(Math.ceil(n/2), n);
//对子数组重新调用本方法
mergesort(_arr1);
mergesort(_arr2);
//实现两个有序数组的合并
merge(_arr1, _arr2, arr);
//返回排过序的结果
return arr;
}else{
return arr;
}
}
/**
* 实现对两个有序数组的合并
* @param {Array} arr1 有序数组
* @param {Array} arr2 有序数组
* @param {Array} arr3
* @return {[Array]} [arr1与arr2两者合并后的顺序数组]
*/
function merge(arr1, arr2, arr3) {
var i = 0, j = 0, k = 0, p = arr1.length, q = arr2.length;
//当两个数组的元素依次比对,小的元素赋值给arr3
while(i < p && j < q){
if(arr1[i] < arr2[j]){
arr3[k] = arr1[i];
i++;
}else{
arr3[k] = arr2[j];
j++;
}
k++;
}
//肯定是一个数组比对完毕,另一个数组未完全用完,因此该数组剩下的数字添加到arr3中
if (i == p ) { //如果arr2未处理完
for(;j < q; j++){
arr3[k] = arr2[j];
k++;
}
} else { //如果arr1未处理完
for(;i < p; i++){
arr3[k] = arr1[i];
k++;
}
}
};
console.log(mergesort([8,3,2,9,7,1,5,4]));
</script>
</html>
三、算法分析
若输入规模是2的乘方,则键值的比较次数C(n) = 2C(n/2) + Cmerge(n), C(1) = 0;其中Cmerge(n)是合并阶段的键值比较次数。
最差的情况下,Cmerge(n) = n - 1;此时,C(n) = 2C(n/2) + n - 1;因此根据主定律C(n)属于Θ(n logn); Cworst = nlog2n - n + 1
浙公网安备 33010602011771号