提问式算法速通--排序
ask:JS 实现快速排序
answer:这是一个简单的快速排序实现,可以根据需要进行优化。
const quickSort = (arr)=>{ if(arr.length<=1) return arr const left = [],right = [],center = arr[0] for(let i = 1; i < arr.length; i++){ if(arr[i] < center){ left.push(arr[i]) }else{ right.push(arr[i]) } } return [...quickSort(left), center, ...auickSort(right)] }
ask:如果要优化,有哪些优化方向
answer:针对小数组的优化: 对于小规模的数组,使用插入排序可能比快速排序更有效。可以在递归的过程中切换到插入排序,从而减少递归的深度。尾递归优化: 尾递归是一种优化技术,可以减少递归调用的堆栈空间使用。在一些 JavaScript 引擎中,尾递归优化可能会生效,但并非所有都支持。三路快速排序: 为了处理重复元素,可以采用三路快速排序,将数组划分为小于、等于和大于基准点的三个部分,以减少相同元素的多次比较。
ask:JS 实现插入排序
answer:
const insertSort = (arr) => { const n = arr.length for (let i = 1; i < n; i++) { let one = arr[i] let j = i - 1 while (j > -1 && arr[j] > one) { arr[j + 1] = arr[j] j-- } arr[j + 1] = one } return arr }
ask:JS 实现选择排序
answer:
const selectSort = (arr) => { const n = arr.length for (let i = 0; i < n - 1; i++) { let min = i for (let j = i + 1; j < n; j++) { if (arr[j] < arr[min]) { min = j } } if (min != i) { [arr[i], arr[min]] = [arr[min], arr[i]] } } return arr }
ask:还有那些排序算法
answer:
除了快速排序、选择排序,还有许多其他排序算法,其中一些常见的包括:
- 冒泡排序(Bubble Sort): 通过多次遍历数组,比较相邻元素并交换,将最大(或最小)元素冒泡到数组末尾(或开头)。
- 插入排序(Insertion Sort): 通过构建有序序列,逐个将未排序的元素插入到已排序部分的合适位置。
- 归并排序(Merge Sort): 采用分治法,将数组分为两个子数组,分别排序,然后合并这两个子数组以得到最终有序数组。
- 堆排序(Heap Sort): 利用堆的数据结构进行排序,通过构建最大堆或最小堆来实现。
- 计数排序(Counting Sort): 针对具有一定范围的整数进行排序,通过统计每个元素出现的次数并计算累积次数,然后将元素放置到正确的位置。
- 桶排序(Bucket Sort): 将元素分配到不同的桶中,每个桶内再进行排序,最后按顺序合并各个桶的元素。
- 基数排序(Radix Sort): 按照数字的个位、十位、百位等顺序进行排序,是一种多关键字的排序算法。
ask:JS 实现归并排序
answer:
const mergeSort = (arr = []) => { if (arr.length <= 1) return arr const mIndex = Math.floor(arr.length / 2) const left = arr.slice(0, mIndex) const right = arr.slice(mIndex) return merge(mergeSort(left), mergeSort(right)) } const merge = (left = [], right = []) => { let arr = [], rIndex = 0, lIndex = 0 while (lIndex < left.length && rIndex < right.length) { if (left[lIndex] < right[rIndex]) { arr.push(left[lIndex]) lIndex++ } else { arr.push(right[rIndex]) rIndex++ } } return arr.concat(left.slice(lIndex).concat(right.slice(rIndex))) }
JS实现冒泡排序
const bubbleSort = (arr=[])=>{ const n = arr.length for(let i = 0;i<n-1;i++){ for(let j = 0;j<n-1-i;j++){ if(arr[j]>arr[j+1]){ [arr[j],arr[j+1]] = [arr[j+1],arr[j]] } } } return arr }
JS实现桶排序
桶排序的思路是,当元素均匀分布在一个范围内的情况,然后对每个桶内的元素进行排序,最后合并,实现 最终还是需要一个排序方法
分别说明上面排序的时间复杂度
- 快速排序(Quick Sort):平均时间复杂度:O(n log n)最坏情况时间复杂度:O(n^2)(当选择的基准点极端不平衡时)最好情况时间复杂度:O(n log n)
- 插入排序(Insertion Sort):平均时间复杂度:O(n^2)最坏情况时间复杂度:O(n^2)最好情况时间复杂度:O(n)(在数组已经基本有序的情况下)
- 选择排序(Selection Sort):平均时间复杂度:O(n^2)最坏情况时间复杂度:O(n^2)最好情况时间复杂度:O(n^2)(因为无论如何都需要进行相同数量的比较和交换)
- 归并排序(Merge Sort):平均时间复杂度:O(n log n)最坏情况时间复杂度:O(n log n)最好情况时间复杂度:O(n log n)
- 冒泡排序(Bubble Sort):平均时间复杂度:O(n^2)最坏情况时间复杂度:O(n^2)最好情况时间复杂度:O(n)(在数组已经有序的情况下)
这些复杂度分析是基于比较排序的一般情况。特定情境下,不同的算法可能表现更好或更差。例如,对于小规模数据或近乎有序的数据,插入排序可能更优。
时间复杂度排序
以下是上述时间复杂度按照增长趋势从低到高的排序:
- O(1) - 常数时间
- O(log n) - 对数时间
- O(n) - 线性时间
- O(n log n) - 线性对数时间
- O(n^2) - 平方时间
- O(n^k) - 多项式时间
- O(2^n) - 指数时间
- O(n!) - 阶乘时间
这个排序反映了这些时间复杂度的相对增长速度。更低阶的复杂度通常表示更高效的算法。然而,在具体情况下,常数因子和实际数据分布等因素也很重要,所以在选择算法时,需要综合考虑多个方面。