常用排序,快速排序,归并排序算法讲解

文章目录

排序有很多种算法,常听的十大排序有:冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序、希尔排序、计数排序、基数排序、桶排序。

这里只介绍两个常用的算法。

排序:

  1. 快速排序
  2. 归并排序

你可能想知道什么时候该用哪个:

快速排序使用场景:快速排序平均时间复杂度为O(n log n),最坏情况下为O(n²),不太稳定,但优点是不占用额外空间,快速排序为原地排序。 在实践中,快速排序通常优于其他时间复杂度为 O(n log n) 的算法,

归并排序使用场景:时间复杂度为O(n log n)。无论情况好坏都相对稳定。优点是稳定,但需要占用额外的O(n)空间。


快速排序

思路:选择一个基准元素,将所有小于基准的元素放置在其左侧,将所有大于基准的元素放置在其右侧。这种操作称为“分区”。然后分别对基准左侧和右侧的两个子元素执行相同的操作。

现在开始快速排序的基本步骤思路:

1: 数据数组

在这里插入图片描述
2: 选择基准

在这里插入图片描述

3: 设置左边界和右边界

在这里插入图片描述
4: 如果右边界小于基准值,则调换左边界和右边界的值,接着左边界i++,随后右边界j++(如果循环未结束)。否则仅j++

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

如果不理解,请仔细阅读第四标题的内容:如果右边界小于基准值,则调换左边界和右边界的值,接着左边界i++,随后右边界j++(如果循环未结束)。否则仅j++

5: 循环结束后,交换左边界和基准的值

在这里插入图片描述

6: 根据基准,截取两部分的值

在这里插入图片描述
7:将左右两部分分别执行 1-6 的步骤

在这里插入图片描述

JavaScript实现代码:

function myQuickSort(array, left = 0, right = array.length - 1) {
    
    
    if (left < right) {
    
    
        // 获取分区后枢轴的位置
        let pivotIndex = pivotIndexMeth(array, left, right)
        // 递归调用
        myQuickSort(array, left, pivotIndex - 1)
        // 递归调用
        myQuickSort(array, pivotIndex + 1, right)
    }
    return array
}

function pivotIndexMeth(array, left, right) {
    
    
    // 使用最右边的元素作为枢轴
    let pivot = array[right]
    // 从左边开始
    let i = left;
    // 遍历数组
    for (let j = left; j < right; j++) {
    
    
        // 如果元素小于枢轴,就交换它和当前的“i”元素
        if (array[j] < pivot) {
    
    
            [array[i], array[j]] = [array[j], array[i]]
            i++
        }
    }
    // 最后,将枢轴放置在正确的位置
    [array[i], array[right]] = [array[right], array[i]]
    // 返回枢轴的位置
    return i;
}

console.log(myQuickSort([7, 2, 3, 1, 6, 8, 4, 5]))

归并排序

思路:将一个大列表分成两个较小的子列表,然后分别对两个子列表进行排序,最后将两个已排序的子列表合并为一个完整的排序列表。

现在开始归并排序的基本步骤思路:

1: 数据数组

在这里插入图片描述

2: 求出中心点,分割数据

在这里插入图片描述
3: 将分割后的数据继续分割

在这里插入图片描述

4: 将分割后的数据继续分割

在这里插入图片描述
5: 直至分割成一个单位长度的数组之后,进行大小对比排序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

JavaScript实现代码:

function myMergeSort(array) {
    
    
    // 获取数组长度
    let len = array.length;
    // 如果数组长度小于2,返回
    if (len < 2) {
    
    
        return array;
    }
    // 获取中间值
    let middle = Math.floor(len / 2)
    // 获取左边的数组
    let left = array.slice(0, middle)
    // 获取右边的数组
    let right = array.slice(middle)
    // 递归调用
    return merge(myMergeSort(left), myMergeSort(right))
}

function merge(left, right) {
    
    
    // 定义一个数组
    let result = [];
    // 如果左边和右边的数组都有值
    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;
}

console.log(myMergeSort([7, 2, 3, 1, 6, 8, 4, 5]))

如果解释有误或需要补充,感谢您指正。

猜你喜欢

转载自blog.csdn.net/qq_41974199/article/details/131647559