八大排序手写

1、选择排序

//给一堆,每次从剩下的元素中间挑最小的和当前元素(i对应的)去比,若更小则交换
const arr =[911,520,888,666,555,2323];
function chooseSort(arr){
    let minIndex;
    let temp;//当前值,用于交换
    for(let i=0;i<arr.length;i++){//遍历每个位置
        //从剩下元素中找最小的(比当前元素更小的)
        minIndex=i;//初始最小下标设置为当前元素
        for(let j=i+1;j<arr.length;j++){
            if(arr[j]<arr[minIndex]){
                minIndex=j;//记录最小元素下标
            }
        }
        //找完了,交换i和minIndex
        temp=arr[i];
        arr[i]=arr[minIndex];
        arr[minIndex]=temp;
    }
    return arr
}
console.log(chooseSort(arr))

2、插入排序

function insertSort(arr){
    //进行插入排序
    let temp;//当前值,用于交换
    //第一个元素肯定有序
    for(let i=1;i<arr.length;i++){//遍历每个位置
        temp=arr[i];
        //找i前面的
        let j=i-1;
        for(;j>=0;j--){
            //大于的则挪
            if(arr[j]>temp){
                //依次把元素往后挪,
                arr[j+1]=arr[j];
                console.log(arr[j+1])
            }else{
                break;
            }
        }
        arr[j+1]=temp;//插入把当前元素插入到该放的位置
    }
}
const arr =[911,520,888,666,555,2323];
insertSort(arr,3);
console.log(arr)

3、归并排序

//两个有序数组的合并排序//依次遍历两个有序数组的元素进行比较,排序
const arrS=[1,3,5,7,2,4,6];
function mergeScopedSort(arrS,statr1,end1,start2,end2,newArr){
    let i=statr1;
    let j=start2;
    let index=statr1;//新数组下标
    while(i<=end1&&j<=end2){
        if(arrS[i]<=arrS[j]){
            newArr[index++]=arrS[i++];
        }else{
            newArr[index++]=arrS[j++];
        }
    }
    //注意有些数组结束要把剩下的加进来
    while(i<=end1){
        newArr[index++]=arrS[i++];
    }
    while(j<=end2){
        newArr[index++]=arrS[j++];
    }
    //把statr1,end1,start2,end2的元素拷贝到原容器
    for(let i=0;i<arrS.length;i++){
        if(newArr[i]!==undefined){
            arrS[i]=newArr[i]
        }
    }
}
/*//测试第一个函数
const newArrS=new Array(arrS.length);
mergeScopedSort(arrS,0,3,4,6,newArrS)
console.log(newArrS)*/

//一个元素肯定有序
//把每单个元素当作一组必定有序,再合并成两两一组有序,再接着依次类推
//使用递归是从大到小
function mergeSort(arr,left,right,newArr){
    //递归结束
    if(left>=right){
        return;
    }
    let mid=parseInt((left+right)/2);
    mergeSort(arr,left,mid,newArr);//排序左边
    mergeSort(arr,mid+1,right,newArr);//排序右边
    //再合并两边
    mergeScopedSort(arr,left,mid,mid+1,right,newArr);
}
const arr =[911,520,888,666,555,2323];
const newArr=new Array(arr.length);//新数组装排序后的数组,避免更改原数组导致频繁交换
mergeSort(arr,0,arr.length-1,newArr)
console.log(newArr)

4、希尔排序

//分组排序
//间隔gap的分为一组,第一步间隔为总长度的一半,组内排序(交换)//重新设置分组间隔,间隔减半(gap初始值可任取重设时也可以任意规则)
//间隔为1时进行插入排序,
//希尔排序就是对插入排序的改良,因为元素少和基本有序的时候插入排序的效率更高
//最本质的原因,就是在序列比较多的时候,效率比较高,交换次数和比较次数相对较少
function ShellSort(arr,initGap){
    let gap=initGap;
    let temp;//当前值,用于交换
    while(gap>1){
        gap=parseInt(gap/2);
        //对每一组进行插入排序
        //第一个元素肯定有序
        for(let i=gap;i<arr.length;i++){//遍历每个位置
            temp=arr[i];
            //找i前面的
            let j=i-gap;
            for(;j>=0;j=j-gap){
                //大于的则挪
                if(arr[j]>temp){
                    //依次把元素往后挪,
                    arr[j+gap]=arr[j];
                }else{
                    
                    break;
                }
            }
            arr[j+gap]=temp;//插入把当前元素插入到该放的位置
        }
    }
}
const arr =[911,520,888,666,555,2323];
ShellSort(arr,4);
console.log(arr);

5、冒泡排序

//相邻两个元素从头到尾比,根据条件选择是否交换
const arr =[911,520,888,666,555,2323];
function bubbleSort(arr){
    let temp;
    //i是循环次数(因为最后还剩一个时不用对比,n-1,n-2,...,1),j是指针(每次都是相邻的两个元素对比)
   
    for(let i=0;i<arr.length-1;i++){
        // for(j=0;j<arr.length-1;j++){
        //优化
        for(j=0;j<arr.length-1-i;j++){
             //先把最大弄最后,接着第二大,第三大等等
            if(arr[j]>arr[j+1]){
                //相邻两个元素比较交换
                temp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
    }
    return arr
}
console.log(bubbleSort(arr))

6、快速排序

//二分法
const arr =[911,520,888,666,555,2323];
function quickSort(arr){
    if(arr.length<2){
        return arr;//结束递归
    }
    let basisIndex=parseInt(arr.length/2);//基准
    const left=[];
    const right=[];
    for(let i=0;i<arr.length;i++){
        if(i!=basisIndex){
            if(arr[i]<arr[basisIndex]){
                left.push(arr[i]);
            }else{
                right.push(arr[i]);
            }
        }
    }
    return quickSort(left).concat([arr[basisIndex]],quickSort(right))
}
console.log(quickSort(arr))//这里写的函数未改变原数组
console.log(arr)

7、计数排序

function countSort(arr){
    let min=arr[0];
    let max=arr[0];
    //遍历得到数组的最大值和最小值
    for (let i = 0; i < arr.length; ++i)
	{
		if (arr[i] > max){max = arr[i];}
		if (arr[i] < min){min = arr[i];}
	}
    let range=max-min+1;//数组中元素的范围
    let count=new Array(range).fill(0);
    //计数
    for (let i = 0; i < arr.length; ++i)
	{
		count[arr[i]-min]++;
	}
    //根据计数数组排序
    let i=0;
    for(let j=0;j<range;j++){
        while(count[j]--){
            arr[i++]=j+min;
        }
    }
}
const arr =[911,520,888,666,555,2323];
countSort(arr)
console.log(arr)

8、堆排序

//堆排序(HeaoSort)是基于数据结构堆设计的一种排序算法,通过堆来选择数据,向上(向下)调整,得到小数(大数),然后再与堆底数据进行交换,即可排序,
//需要注意的是排升序建大堆,排降序建小堆
function swap(arr,childrenIndex,parentIndex){
    let temp=arr[childrenIndex];
    arr[childrenIndex]=arr[parentIndex];
    arr[parentIndex]=temp;
}
//根据数组建大堆
//1堆中节点的向下调整算法
//最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
function adjustDown(arr,startRoot,n){
    let parentIndex=startRoot;
    let childrenIndex=parentIndex*2+1;//左子节点在数组中对应的下标
    while(childrenIndex < n){
        if(childrenIndex+1<n&&arr[childrenIndex+1]>arr[childrenIndex]){
            childrenIndex++;//找到子节点中最大的节点
        }
        //判断子节点和父节点谁大
        if(arr[childrenIndex]>arr[parentIndex]){
            swap(arr,childrenIndex,parentIndex);
            parentIndex=childrenIndex;
            childrenIndex=parentIndex*2+1;
        }else{
            break;
        }
    }
}
function heapSort(arr){
    let n=arr.length;
    //建最大堆 //这里元素的索引是从0开始的,所以最后一个非叶子结点array.length/2 - 1
    //从最后一个父亲节点遍
    for(let i = parseInt((n - 1 - 1) / 2); i >= 0; --i){
        adjustDown(arr,i,n);//调整堆(调整为当前节点和其后面的节点符合最大堆)
    }
    //得到最大堆后,进行排序
    for (let j = arr.length - 1; j > 0; j--) {
        // 把最大堆的根元素,放到数组的最后;
        //换句话说,就是每一次的堆调整之后,都会有一个元素到达自己的最终位置
        swap(arr, 0, j);//每次得到一个第n-j大元素放在数组后面响应的位置
        // 最大元素放到最后之后,要对当前堆中(除最后一个),进行最大堆值调整
        adjustDown(arr, 0, j);
    }
    return arr;
}
const arr =[911,520,888,666,555,2323];
heapSort(arr);
console.log(arr)

总结和比较:各种排序算法的时间复杂度和空间复杂度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值