您的位置:首页 > Web前端 > JavaScript

排序算法总结二(JavaScript)

2017-08-10 16:05 260 查看
1、归并排序(自顶向下)

复杂度: O(nlogn)               稳定

保留副本需要开辟额外n个存储空间,以空间换取时间效率

//将左右两部分数组进行归并,保留原数组的一个副本,一个一个比较左右两个部分数组元素的大小,将副本的相应元素放到数组中
function __merge(arr,l,mid,r){
var copy=[];
for(var m=l;m<=r;m++){
copy[m]=arr[m];
}
var i=l,j=mid+1;
for(var k=l;k<=r;k++){
if(i>mid){              //左边部分已完成归并
arr[k]=copy[j];
j++;
}
else if(j>r){          // 右边部分已完成归并
arr[k]=copy[i];
i++;
}
else if(copy[i]<copy[j]){     //左边部分的元素大,将该元素添加到数组中,左边索引 i 右移
arr[k]=copy[i];
i++;
}
else{
arr[k]=copy[j];      //右边部分的元素大,将该元素添加到数组中,右边索引 j 右移

j++;
}
}

}

//递归调用归并排序函数对整个数组进行排序
function __mergeSort(arr,l,r){
if(l>=r){
return;
}
var mid=Math.floor((l+r)/2);
__mergeSort(arr,l,mid);
__mergeSort(arr,mid+1,r);
//若左边最大值比右边最小值大,则进行归并操作,否则表示两部分已有序,不需要再进行归并
if(arr[mid]>arr[mid+1]){
__merge(arr,l,mid,r);
}
}
function mergeSort(arr){
var n=arr.length;
__mergeSort(arr,0,n-1);
return arr;
}


2、归并排序(自底向上)

function __merge(arr,l,mid,r){
var copy=[];
for(var m=l;m<=r;m++){
copy[m]=arr[m];
}
var i=l,j=mid+1;
for(var k=l;k<=r;k++){
if(i>mid){
arr[k]=copy[j];
j++;
}
else if(j>r){
arr[k]=copy[i];
i++;
}
else if(c
c324
opy[i]<copy[j]){
arr[k]=copy[i];
i++;
}
else{
arr[k]=copy[j];
j++;
}
}

}
//若不进行优化  则可以用来对链表进行排序,因为排序中没有用到数组的下标
function mergeSortBU(arr){
var n=arr.length;
var size,i;
//分轮次进行归并,每轮归并的元素数量为size
for(size=1;size<n;size+=size){
//每轮归并分组进行
for(i=0;i+size<n;i+=size+size){
//优化:如果两边已经有序就不在进行归并
if(arr[i+size-1]>arr[i+size]){
__merge(arr,i,i+size-1,Math.min(i+size+size-1,n-1));   //防止越界
}
}
}
return arr;
}

3、快速排序(三路快排序)

复杂度: O(nlogn)           不稳定

不需要开辟额外空间

function __quickSort(arr,l,r){
if(l>=r){
return;
}
//三路: 分为三部分  比参考元素小:arr[l+1....lt] 等于参考元素: arr[lt+1....i] 大于参考元素: arr[gt...r];
var v=arr[l];     //取第一个元素为参考
var lt=l;
var gt=r+1;
var i=l+1;
while(i<gt){
if(arr[i]<v){        //比参考元素小的与lt+1交换
var temp=arr[i]; arr[i]=arr[lt+1]; arr[lt+1]=temp;
lt++;
i++;
}
else if(arr[i]>v){     //比参考元素大的与gt-1交换
var temp2=arr[i]; arr[i]=arr[gt-1]; arr[gt-1]=temp2;
gt--;
}
else{           //与参考元素相等直接右移
i++;
}
}
//将参考元素放到合适的位置
var temp1=arr[l];
arr[l]=arr[lt];
arr[lt]=temp1;
//递归对左右两部分进行快排序
__quickSort(arr,l,lt-1);
__quickSort(arr,gt,r);
}
function quickSort(arr){
var n=arr.length;
__quickSort(arr,0,n-1);
return arr;
}


4、堆排序

复杂度: O(nlogn)         不稳定

原地堆排序,不需要开辟额外空间

//left child (i)=2*i+1      right child (i)=2*i+2     parent(i)=(i-1)/2
//最后一个非叶子节点的索引: (n-1)/2
//构建最大堆的函数
function shiftDown(arr,n,k){
//要保证左孩子在n范围内   并且该节点比其左孩子或右孩子中任意一个小
while((2*k+1)<n && (arr[k]<arr[2*k+1] || (arr[k]<arr[2*k+2]&&2*k+2<n))){
//有右孩子且右孩子比左孩子大
if(2*k+2<n&&arr[2*k+1]<arr[2*k+2]){
[arr[k],arr[2*k+2]]=[arr[2*k+2],arr[k]];
k=2*k+2;
}else{            //包含右孩子比左孩子小和没有右孩子两种情况
[arr[k],arr[2*k+1]]=[arr[2*k+1],arr[k]];
k=2*k+1;
}
}
}
function heapSort(arr){
var n=arr.length;
//将数组构建成最大堆
for(var i=Math.floor((n-1)/2);i>=0;i--){
shiftDown(arr,n,i);
}
for(var j=n-1;j>0;j--){
//堆顶元素最大,每次将堆顶元素与最后一个元素交换
[arr[j],arr[0]]=[arr[0],arr[j]];
//如果待排序元素数大于1,则进行堆重构;等于1说明已经完成排序
if(j>1){
shiftDown(arr,j,0);
}else{
break;
}
}
return arr;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: