算法与数据结构 排序算法

104 阅读1分钟

计数排序

可以说是右移负数直方图,然后对直方图再进行整理后的排序

可以进行改善,就是再那个计数的那个可以进行修改countArr变成距离而不是最大值驱动

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArray = function(nums) {
    // 时间复杂度 n+k
    // 空间复杂度 n+k
    // 使用计数排序
    // 时间 计数排序步骤是;
    //  第一步:算出最大值、最小值、以及之间的距离
    let min = nums[0],max = nums[0]
    for(let i = 1;i < nums.length;i++){
        min = Math.min(nums[i],min)
        max = Math.max(nums[i],max)
    }
    let d = max - min
    // 如果是负数需要额外添加一些数字
    let add =  min < 0?-min:0
    // 第二步:创建一个计数的数组,用来存储数据对应的次数
    let countArr = new Array(max+add+1).fill(0)
    for(let i = 0;i < nums.length;i++){
        // 对应的下标
        let index = nums[i]+add
        countArr[index]++
    }
    // 第三步:对已经存储的次数进行排序
    let arr = []
    for(let i = 0;i < countArr.length;i++){
        if(countArr[i] === 0){
            continue
        }
        let count = countArr[i]
        // 下标表示数字,值表示次数,然后将对应的次数进行push
        while(count !== 0){
            // 如果是负数的话,需要减去转化为整数的值
            arr.push(i-add)
            count--
        }
    }
    return arr
  // 09点03分
};

快速排序

  • 时间复杂度 nlog2n
  • 空间复杂度 nlog2n

主要是递归的使用,然后还有将数组截取成两段使用splice,把小的放在左边,大的放在右边,然后再进行拼合,

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArray = function(nums) {
    // 快速排序
    var quickSort  = (arr) => {
        if(arr.length == 1 || arr.length === 0) return arr
        // 第一步:确定左边、右边和中间数
        let left = [],right = [], mid = Math.floor(arr.length / 2)
        let midNum = arr[mid]
        // 第二步,对中间数进行截取,使用splice可以对数组直接进行修改
        arr.splice(mid,1)
        for(let i = 0;i < arr.length;i++){
            if(arr[i] < midNum){
                left.push(arr[i])
            }else{
                right.push(arr[i])
            }
        }
        return quickSort(left).concat(midNum,quickSort(right))
    }
    return quickSort(nums)
};

归并排序

本质上就是变成两个有序数组然后进行排序

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArray = function(nums) {
    // 09点36分 归并排序
    // 先把它进行拆分,然后比较,知道最后一个,然后进行合并
    // 10点51分 玩了一会儿
    // 第二个步骤,对两个进行合并
    // 12点10分
    let merge = (left,right) => {
        // 进行合并
        let result = []
        let leftIndex = 0 ,rightIndex = 0
        while(leftIndex < left.length && rightIndex < right.length){
            let tem = left[leftIndex] < right[rightIndex] ? left[leftIndex++]:right[rightIndex++]
            result.push(tem) 
        }
        while(leftIndex < left.length){
            result.push(left[leftIndex++])
        }
        while(rightIndex < right.length){
            result.push(right[rightIndex++]) 
        }
        // while(left.length && right.length){
        //     if(left[0] < right[0]){
        //         result.push(left.shift())
        //     }else{
        //         result.push(right.shift())
        //     }
        // }
        // while(left.length){
        //     result.push(left.shift())
        // }
        // while(right.length){
        //     result.push(right.shift())
        // }
        return result
    }
    // 第一个步骤:进行拆分,分成左边和右边
    let mergeSort = (arr) => {
        if(arr.length <= 1)return arr
        let midIndex = Math.floor(arr.length / 2)
        // 对数组进行拆分
        let left = arr.slice(0,midIndex) //有包含midIndex
        let right = arr.slice(midIndex)
        let mergeLeft = mergeSort(left)
        let mergeRight = mergeSort(right)
        return merge(mergeLeft,mergeRight)
    }
    return mergeSort(nums)
};

插入排序

就是如果前面的比大,让前面的牌到后面去,然后重新

var sortArray = function(nums) {
    // 12点16分 插入排序
    // 就是从后面往前面进行调换
    for(let i = 0;i < nums.length;i++){
        // 进行插入的数组
        let cur = nums[i],
            preIndex = i - 1
            // 如果下标大于0,并且数大于要插入的数的话,就要进行插入
        while(preIndex >= 0 && nums[preIndex] > cur){
            nums[preIndex+1] = nums[preIndex]
            preIndex--
        }
        // 插入的点
        nums[preIndex+1] = cur
    }
    return nums
};

选择排序

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArray = function(nums) {
    // 15点57分 选择排序,找出后面最小的,然后每次放在最前面
    let len = nums.length
    for(let i = 0;i < nums.length;i++){
        // 找出之后的最小值的坐标
        let minIndex = i
        for(let j = i+1;j < nums.length;j++){
            minIndex = nums[minIndex] < nums[j]?minIndex:j
        }
        // 最小坐标对应值进行交换
        let tem = nums[i]
        nums[i] = nums[minIndex]
        nums[minIndex] = tem
    }
    return nums
    // 16点09分
};