数据结构---快速排序详解

简介: 数据结构---快速排序详解

快速排序的递归展开图

了解了快速排序的工作原理,独立画出它的递归展开图有助于了解它的工作原理

在这里插入图片描述

快速排序的优化

快速排序确实是在很多方面都很优秀的排序,但是仅仅用上述的代码并不能完全解决问题,假设现在给的序列是一个按升序排列的序列,那么此时我们选取的key是最小的数据,时间复杂度是O(N^2),但如果每次选取的数据恰好是中位数,那么就是整个数据最高效的方式,时间复杂度是O(NlogN),因此如何优化?

常见的优化有三数取中法和递归到小的子区间选取插入排序法

三数取中法

顾名思义,就是取开头,末尾和中间的三个数,选这三个数中最中间的一个,让这个数作为key

int GetMid(int* a, int left, int right)
{
   
   
    int midi = (left + right) / 2;
    if (a[left] < a[midi])
    {
   
   
        if (a[midi] < a[right])
        {
   
   
            return midi;
        }
        else if (a[left] > a[right])
        {
   
   
            return left;
        }
        else
        {
   
   
            return right;
        }
    }
    else  // a[left] > a[midi]
    {
   
   
        if (a[midi] > a[right])
        {
   
   
            return midi;
        }
        else if (a[left] < a[right])
        {
   
   
            return left;
        }
        else
        {
   
   
            return right;
        }
    }
}

int PartSort1(int* a, int left, int right)
{
   
   
    int midi = GetMid(a, left, right);
    Swap(&a[midi], &a[left]);
    int keyi = left;
    while (left < right)
    {
   
   
        while (left < right && a[right] >= a[keyi])
        {
   
   
            right--;
        }

        while (left < right && a[left] <= a[keyi])
        {
   
   
            left++;
        }

        Swap(&a[left], &a[right]);
    }
    Swap(&a[keyi], &a[left]);

    return left;
}

int PartSort2(int* a, int left, int right)
{
   
   
    int midi = GetMid(a, left, right);
    Swap(&a[midi], &a[left]);
    int key = a[left];
    int hole = left;
    while (left < right)
    {
   
   
        while (left < right && a[right] >= key)
        {
   
   
            right--;
        }

        a[hole] = a[right];
        hole = right;

        while (left < right && a[left] <= key)
        {
   
   
            left++;
        }

        a[hole] = a[left];
        hole = left;
    }

    a[hole] = key;

    return hole;
}

int PartSort3(int* a, int left, int right)
{
   
   
    int midi = GetMid(a, left, right);
    Swap(&a[midi], &a[left]);
    int cur = left+1;
    int prev = left;
    int keyi = left;
    while (cur <= right)
    {
   
   
        if (a[cur] < a[keyi])
        {
   
   
            ++prev;
            Swap(&a[prev], &a[cur]);
        }
        cur++;
    }

    Swap(&a[prev], &a[keyi]);

    return prev;
}

void QuickSort(int* a, int begin, int end)
{
   
   
    if (begin >= end)
    {
   
   
        return;
    }
    int keyi = PartSort1(a, begin, end);

    QuickSort(a, begin, keyi - 1);
    QuickSort(a, keyi + 1, end);
}

快速排序的非递归实现

快速排序是利用递归实现的,而凡是递归就有可能爆栈的情况出现,因此这里要准备快速排序的非递归实现方法

非递归实现是借助栈实现的,栈是在堆上malloc实现的,栈区一般在几十Mb左右,而堆区有几G左右的空间,在堆上完成操作是没有问题的

在这里插入图片描述

当left<keyi-1才会入栈,当keyi+1<right才会入栈

随着不断入栈出栈,区间划分越来越小,left最终会等于keyi-1,这样就不会入栈,右边同理,不入栈只出栈,最终栈会为空,当栈为空时,排序完成

相关文章
|
5月前
|
算法 搜索推荐
快速排序-数据结构与算法
快速排序(Quick Sort)是一种基于分治法的高效排序算法。其核心思想是通过选择基准(pivot),将数组划分为左右两部分,使得左侧元素均小于基准,右侧元素均大于基准,然后递归地对左右两部分进行排序。时间复杂度平均为 O(n log n),最坏情况下为 O(n²)(如数组已有序)。空间复杂度为 O(1),属于原地排序,但稳定性不佳。 实现步骤包括编写 `partition` 核心逻辑、递归调用的 `quickSort` 和辅助函数 `swap`。优化方法有随机化基准和三数取中法,以减少最坏情况的发生。
268 13
|
8月前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
193 7
|
11月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
276 1
|
11月前
【初阶数据结构】打破递归束缚:掌握非递归版快速排序与归并排序
【初阶数据结构】打破递归束缚:掌握非递归版快速排序与归并排序
124 4
|
11月前
|
算法
蓝桥杯宝藏排序 | 数据结构 | 快速排序 归并排序
蓝桥杯宝藏排序 | 数据结构 | 快速排序 归并排序
|
搜索推荐
【数据结构常见七大排序(三)上】—交换排序篇【冒泡排序】And【快速排序】
【数据结构常见七大排序(三)上】—交换排序篇【冒泡排序】And【快速排序】
【数据结构常见七大排序(三)上】—交换排序篇【冒泡排序】And【快速排序】
|
存储 算法 搜索推荐
【初阶数据结构篇】冒泡排序和快速排序(中篇)
与直接插入排序法相比,比较次数一致,但冒泡排序的交换需要执行三次,而直接插入排序因为使用了tmp临时变量存储要插入的数据,只用执行一次,所以直接插入排序法效率明显更高。
71 1
|
算法
数据结构与算法-快速排序
数据结构与算法-快速排序
51 1
|
算法 索引
【数据结构与算法】:非递归实现快速排序、归并排序
上篇文章我们详细讲解了递归版本的快速排序,本篇我们来探究非递归实现快速排序和归并排序
【数据结构与算法】:非递归实现快速排序、归并排序
|
存储 搜索推荐 算法
[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)
[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)
163 1