快速排序

102 阅读2分钟

快速排序的思路是拿一个数字做对比,将数组分段,较小的数字放在左侧,较大的放在右侧。

1. 比较简单的快速排序

思路

  1. 取数组第一个数字
  2. 依次对比,小于该数字的放在数组left中,大于该数字的放在right中,等于该数字的放在mid中
  1. 递归left和right数组,当数组中只有一个元素时结束
  2. 合并三个数组

代码实现

function quickSort(li) {
    if (li.length < 2) return li;
    let left = [],
        mid = [],
        right = [];
    let temp = li[0]
    for (let index = 0; index < li.length; index++) {
        let value = li[index];
        if (value > temp) {
            right.push(value)
        } else if (value < temp) {
            left.push(value)
        } else {
            mid.push(value)
        }
    }
    return quickSort(left).concat(mid, quickSort(right))
}

let testLi = new Array(100);
for (let index = 0; index < testLi.length; index++) {
   testLi[index] = Math.ceil(Math.random() * 100)
}
console.log(testLi)
console.log(quickSort(testLi))

算法缺陷

  1. 该算法一般来说时间复杂度为O(nlogn),但是不稳定,存在一个最坏情况,当原数组时倒序的时候,时间复杂度为O(n2)。
  2. 由于每一次递归都会新建三个数组,所以存在一个空间复杂度O(nlogn)

\

2. 优化算法

思路

为了解决空间复杂度问题,所有操作在原属组上进行

  1. 取数组第一个数字和下标,放在临时变量中,称为tempIndex和tempNum
  2. 指针right从后向前遍历,如果大于等于tempNum,则继续向前走,否则将这个数字放在tempIndex位置,并将tempIndex改right
  1. 指针left从前向后遍历,如果小于tempNum,则继续向后走,否则将这个数字放在tempIndex位置,并将tempIndex改为当前位置
  2. 2和3在在left和right指针相遇时,也就是left等于right时结束,将临时数字tempNum放在结束的位置,这样数组就变成tempNum左侧为小于tempNum的数字,左侧为较大的数字
  1. 递归数组的左侧和右侧,执行1-4步骤
  2. 当数组只有一个元素时结束

代码实现

function quickSort(li, start, end) {
    if (start >= end) return;
    let left = start,
        right = end;
    let tempIndex = start,
        temp = li[tempIndex];
    while (left < right) {
        while (left < right && li[right] >= temp) {
            right--;
        }
        if (left < right) {
            li[tempIndex] = li[right]
            tempIndex = right;
        }
        while (left < right && li[left] < temp) {
            left++
        }
        if (left < right) {
            li[tempIndex] = li[left]
            tempIndex = left;
        }
    }
    li[left] = temp;

    quickSort(li, start, left - 1);
    quickSort(li, left + 1, end)
}


let testLi = new Array(100);
for (let index = 0; index < testLi.length; index++) {
   testLi[index] = Math.ceil(Math.random() * 100)
}
console.log(testLi)
quickSort(testLi, 0, testLi.length - 1)
console.log(testLi)

算法缺陷

该算法不存在空间复杂度的问题,但是也不稳定,对于倒序数组时间复杂度为O(n2)。为了避免这个问题,在选取tempNum的时候,可以随机选取数字中的一个数字,将这个数字和第一个数字交换然后再执行排序。这样出现O(n2)的概率就极小。