归并排序
1.左右两边先排序;
2.再借助辅助数组,指针在左右两个数组中移动,两指针作比较,小的就往辅助数组中填;
3.整体在辅助数组中有序后,拷贝回原数组。
//归并排序 时间复杂度O(n*logn)
var list = [5,2,6,1,22,77,4,12];
console.log('未排序',list);
function merge(arr,l,mid,r){
var help = [];
var i = 0;
var p1 = l;
var p2 = mid + 1;
while(p1 <= mid && p2 <= r){
help[i++] = arr[p1] < arr[p2] ? arr[p1++]:arr[p2++];
}
while(p1 <= mid){
help[i++] = arr[p1++];
}
while(p2 <= r){
help[i++] = arr[p2++];
}
for(i=0; i<help.length; i++){
arr[l+i] = help[i];
}
}
function sortProcess(arr,l,r){
if(l == r){
return;
}
var mid = parseInt((l+r)/2);
sortProcess(arr,l,mid);
sortProcess(arr,mid+1,r);
merge(arr,l,mid,r);
}
function mergeSort(arr){
if(arr == null || arr.length<2){
return;
}
sortProcess(arr,0,arr.length-1);
}
mergeSort(list);
console.log('归并排序',list);
调试结果如下:
报错总结:在没有把mid取整时,出现了无限循环的情况
- 解决:加入
var mid = parseInt((l+r)/2);
若没有控制好判断条件,在递归中也会很容易出现无限循环的情况
递归算法:
系统中一个函数调子过程之前,会将函数、参数…都压入栈中,子过程返回之后,重新调用栈中函数,彻底还原。
( 自己调用自己 )
//递归找最大值
var nums = [4,3,2,1];
var len = nums.length;
function getMax(arr,l,r){
if(l==r){
return arr[l];
}
var mid = parseInt((l+r)/2);
var maxLeft = getMax(arr,l,mid);
var maxRight = getMax(arr,mid+1,r);
return Math.max(maxLeft,maxRight);
}
console.log(getMax(nums,0,len-1));
调试结果如下:
快速排序
1.每一趟排序都将数据分割两部分,左边小,右边大;
2.按此方法对接着将左和右也递归切分;
3.以此达到整个数据变成有序序列
//快速排序 复杂度最坏为O(n^2)
var arr = [4,9,11,1,3,5,88,22,7,2,5];
function quickSort(arr,l,r){
if(l < r){
var p = partition(arr,l,r);
quickSort(arr,l,p[0]-1);
quickSort(arr,p[1]+1,r);
}
}
function partition(arr,l,r){
var less = l - 1;
var more = r;
while(l < more){
if(arr[l] < arr[r]){
swap(arr,++less,l++);
}else if(arr[l] > arr[r]){
swap(arr,--more,l);
}else{
l++;
}
}
swap(arr,more,r);
return new Array(less+1,more);
}
function swap(arr,i,j){
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
quickSort(arr,0,arr.length-1);
console.log('快排',arr);
调试结果如下:
荷兰国旗问题
var arr1 = [4,9,11,1,3,5,88,22,7,2];
var arr2 = [3,1,2,4];
var arr3 = [9,11,55,7];
function partition(arr,l,r,num){
var less = l - 1;
var more = r + 1;
var cur = l;
while(cur < more){
if(arr[cur] < num){
swap(arr,++less,cur++);
}else if(arr[cur] > num){
swap(arr,--more,cur);
}else{
cur++;
}
}
return arr;
}
function swap(arr,i,j){
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
console.log('arr1',partition(arr1,0,arr1.length-1,5));
console.log('都小于num的arr2',partition(arr2,0,arr2.length-1,5));
console.log('都大于num的arr3',partition(arr3,0,arr3.length-1,5));
调试结果如下: