IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 图解快速排序算法(C++ 超详细) 以及 快速选择算法 -> 正文阅读

[数据结构与算法]图解快速排序算法(C++ 超详细) 以及 快速选择算法

什么是快速排序

关键词: 交替填充 或 换位
时间复杂度: O(log2n)

快速排序算法

思路

对于一个排好序的数组,我们假设为从小到大排序。
那么对于这个数组而言,其中的每一个元素,左边都是比它小的元素;
右边都是比它大的元素(若大小相等,在左边或右边都可以)。
所以我们进行排序,可以反过来想,即将每一个元素都放到它应该在的位置。
当放完所有的元素后,排序完成。

做法

那么我们要做的就是一个一个的找到元素所在的位置,并放好他们。
所以我们假设第一个元素为待放置元素。
通过以下的方式将其放置好,之后再递归的将其左边和右边再次进行排序即可。

图解Partition函数(例子)

云观

写法1

将 partition 与 sort 函数写在一个函数里。

函数参数 : nums(需要排序的数组),startIndex(起始元素的下标),endIndex(最后一个元素的下标 + 1)

返回值: void

单层逻辑:先移动 R 指针,若遇到小于基准的值,则进行放置,接着换移动 L 指针。

结束条件: startIndex 与 endIndex 相交或 startIndex > endIndex 
void quicksort1(vector<int> &nums, int startIndex, int endIndex)
{
    if (!(startIndex < endIndex))
        return;
    int left = startIndex, right = endIndex - 1;
    int temp = nums[left];
    while (right > left)
    {
        while (right > left)
        {
            if (nums[right] < temp)
            {
                nums[left] = nums[right];
                left++;
                break;
            }
            right--; // nums[right] > temp
        }
        while (right > left)
        {
            if (nums[left] > temp)
            {
                nums[right] = nums[left];
                right--;
                break;
            }
            left++;
        }
    }
    nums[left] = temp;
    quicksort1(nums, startIndex, left);
    quicksort1(nums, left + 1, endIndex);
}

写法2

将 partition 与 sort 函数写在一个函数里。利用交换。

函数参数 : nums(需要排序的数组),startIndex(起始元素的下标),endIndex(最后一个元素的下标 + 1)

返回值: void

单层逻辑:先移动 R 指针若找到小于 temp 的值,停止;移动 L 指针找到大于 temp 的值,停止;
交换 L 与 R的值,继续循环直到 L 与 R相交,交换 基准位置与 R 位置

结束条件: startIndex 与 endIndex 相交或 startIndex > endIndex
void quicksort2(vector<int> &nums, int startIndex, int endIndex)
{
    if (!(startIndex < endIndex))
        return;
    int left = startIndex, right = endIndex - 1;
    int &temp = nums[startIndex];
    while (left < right)
    {
        while (left < right)
        {
            if (nums[right] < temp)
            {
                break;
            }
            right--;
        }
        while (left < right)
        {
            if (nums[left] > temp)
            {
                break;
            }
            left++;
        }
        swap(nums[left], nums[right]);
    }
    swap(temp, nums[left]);
    quicksort2(nums, startIndex, left);
    quicksort2(nums, left + 1, endIndex);
}

写法3

将 sort 与 partition分开写
sort 函数:
函数参数:nums(待排序数组), startIndex(排序开始位置), endIndex(排序结束位置的后一个位置)。
返回值:void
单层逻辑:先利用partition函数排好第一个元素,取得元素位置,排序元素位置的左边与右边。
结束条件:startIndex 超过 endIndex 或 与其相交。

partition函数:
函数参数:nums(待排序数组), startIndex(排序开始位置), endIndex(排序结束位置的后一个位置)。
返回值:int 排好位置后的合适位置
单层逻辑:定好 L 与 R 的含义,分别指向最左与最右,设置基准兵,开始比较以及调整数组位置。
结束条件:L == R
void quicksort(vector<int> &nums, int startIndex, int endIndex)
{
    if (!(startIndex < endIndex))
        return;
    int pivot = partition(nums, startIndex, endIndex - 1);
    quicksort(nums, startIndex, pivot);
    quicksort(nums, pivot + 1, endIndex);
}

int partition(vector<int> &nums, int startIndex, int endIndex)
{
    int pivot = startIndex;
    int temp = nums[startIndex];
    int left = startIndex, right = endIndex;
    while (left < right)
    {
        while (left < right)
        {
            if (nums[right] < temp)
            {
                nums[left] = nums[right];
                left++;
                break;
            }
            right--;
        }
        while (left < right)
        {
            if (nums[left] > temp)
            {
                nums[right] = nums[left];
                right--;
                break;
            }
            left++;
        }
    }
    nums[left] = temp;
    return left;
}

快速选择算法

快速选择算法,基于快速排序算法演化而来的算法。
上文写道:我们可以得到任意一个值应该安排到的位置,假如我们要找第 3 大的元素,那么按照从小到大排序,它在下标为size() - 3的位置,我们从而可以采取上文的 partition 函数。
具体怎么使用呢?
我们知道使用一次partition函数,会返回一个当前元素的正确排序下标。
假设这个下标为size() - 3,是不是就表示我们找到了这个第三大的元素了?
假设这个下标为size() - 4,那么答案则在它的右边,而它的左边我们则不需要去考虑了。
这就比排序所有的元素要快。
下面我们来举一个例子。

图解快速选择算法(例子)

在这里插入图片描述

写法1

关键词: 基于快速排序的选择算法
时间复杂度: O(n)

int nLargeNum(vector<int> &nums, int startIndex, int endIndex, int n)
{
    int pivot = partition(nums, startIndex, endIndex - 1);  // 同上文
    if (pivot == n - 1)
        return nums[pivot];
    else if (n > pivot + 1)
    {
        return nLargeNum(nums, pivot + 1, endIndex, n);
    }
    else
    {
        return nLargeNum(nums, startIndex, pivot, n);
    }
}

递归三部曲 – 来自代码随想录

1. 确定函数参数与返回值

2. 确定结束递归的条件

3. 确定单层递归逻辑

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:39:02  更:2022-10-22 21:40:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 2:50:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计