前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >快速排序的思想、时间复杂度、实现以及优化方法

快速排序的思想、时间复杂度、实现以及优化方法

原创
作者头像
代码小李
发布于 2024-12-30 07:31:40
发布于 2024-12-30 07:31:40
3190
举报

快速排序的思想

快速排序(Quicksort)是一种高效的排序算法,采用分治法(Divide and Conquer)的策略。其基本思想是:

  1. 选择一个基准值(Pivot):从数组中选择一个元素作为基准值。
  2. 分区操作(Partition):将数组分为两部分,一部分的所有元素都小于基准值,另一部分的所有元素都大于或等于基准值。
  3. 递归排序:对这两部分分别递归地进行快速排序。

时间复杂度

  • 最佳情况:O(n log n),当每次分区都能均匀分割数组时。
  • 平均情况:O(n log n),在大多数情况下,快速排序的性能接近最佳情况。
  • 最坏情况:O(n^2),当每次分区都选择最小或最大元素作为基准值时,例如数组已经有序或逆序。

实现

以下是一个简单的快速排序实现:

代码语言:txt
复制
#include <stdio.h>

// 交换两个元素
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

// 分区函数
int partition(int arr[], int low, int high) {
    int pivot = arr[high];  // 选择最后一个元素作为基准值
    int i = (low - 1);  // 小于基准值的元素的索引

    for (int j = low; j <= high - 1; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    return (i + 1);
}

// 快速排序函数
void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);

        quickSort(arr, low, pi - 1);  // 递归排序左子数组
        quickSort(arr, pi + 1, high); // 递归排序右子数组
    }
}

// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[] = {10, 7, 8, 9, 1, 5};
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("原始数组: ");
    printArray(arr, n);

    quickSort(arr, 0, n - 1);

    printf("排序后的数组: ");
    printArray(arr, n);

    return 0;
}

优化方法

选择更好的基准值
  • 随机选择基准值:通过随机选择基准值可以减少最坏情况的发生概率。
  • 三数取中法:选择数组的第一个、中间和最后一个元素的中位数作为基准值。

  1. 尾递归优化
    • 在递归调用时,优先处理较小的子数组,这样可以减少递归深度,避免栈溢出。
  2. 小数组使用插入排序
    • 对于小数组,插入排序通常比快速排序更高效。可以在数组大小小于某个阈值时切换到插入排序。
  3. 非递归实现
    • 使用迭代和栈来实现快速排序,避免递归带来的栈溢出问题。

示例代码优化

以下是一个包含上述优化的快速排序实现:

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// 交换两个元素
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

// 三数取中法选择基准值
int medianOfThree(int arr[], int low, int high) {
    int mid = low + (high - low) / 2;
    if (arr[low] > arr[mid]) swap(&arr[low], &arr[mid]);
    if (arr[low] > arr[high]) swap(&arr[low], &arr[high]);
    if (arr[mid] > arr[high]) swap(&arr[mid], &arr[high]);
    return mid;
}

// 分区函数
int partition(int arr[], int low, int high) {
    int pivotIndex = medianOfThree(arr, low, high);
    int pivot = arr[pivotIndex];
    swap(&arr[pivotIndex], &arr[high]);  // 将基准值移到末尾
    int i = (low - 1);  // 小于基准值的元素的索引

    for (int j = low; j <= high - 1; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    return (i + 1);
}

// 插入排序
void insertionSort(int arr[], int low, int high) {
    for (int i = low + 1; i <= high; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= low && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

// 快速排序函数
void quickSort(int arr[], int low, int high) {
    while (low < high) {
        if (high - low < 10) {  // 小数组使用插入排序
            insertionSort(arr, low, high);
            break;
        } else {
            int pi = partition(arr, low, high);
            if (pi - low < high - pi) {
                quickSort(arr, low, pi - 1);  // 优先处理较小的子数组
                low = pi + 1;
            } else {
                quickSort(arr, pi + 1, high);
                high = pi - 1;
            }
        }
    }
}

// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[] = {10, 7, 8, 9, 1, 5, 3, 2, 6, 4};
    int n = sizeof(arr) / sizeof(arr[0]);

    srand(time(NULL));  // 初始化随机数生成器

    printf("原始数组: ");
    printArray(arr, n);

    quickSort(arr, 0, n - 1);

    printf("排序后的数组: ");
    printArray(arr, n);

    return 0;
}

总结

快速排序是一种高效的排序算法,通过分治法将数组分成两部分并递归排序。通过选择更好的基准值、尾递归优化、小数组使用插入排序和非递归实现等方法,可以进一步提高快速排序的性能和稳定性。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
十种排序方法
在C语言中,有多种排序算法可供选择,每种都有其独特的特点和应用场景。以下是几种常见的排序算法及其在C语言中的总结:
ljw695
2024/10/18
1660
大佬的快速排序算法,果然不一样
快速排序,正如它的名字所体现,是在实践中已知的最快的排序算法,平均运行时间为O(NlogN),最坏的运行时间为O(N^2)。算法的基本思想很简单,然而想要写出一个高效的快速排序算法并不是那么简单。基准的选择,元素的分割等都至关重要,如果你不清楚如何优化快速排序算法,本文你不该错过。
IT大咖说
2019/05/07
6380
python 排序
插入排序是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
织幻妖
2021/03/01
7110
python 排序
文心一言 VS 讯飞星火 VS chatgpt (78)-- 算法导论7.4 2题
快速排序是一种分治算法,它将一个数组分成两个子数组,然后对这两个子数组分别进行排序。在最好情况下,每次划分都能将数组等分,即每次划分后得到的两个子数组的长度相等。
福大大架构师每日一题
2023/08/29
1890
文心一言 VS 讯飞星火 VS chatgpt (78)-- 算法导论7.4 2题
算法解析(挖坑法/快速排序)
算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,代表着用系统的方法描述解决问题的策略机制。它能对一定规范的输入,在有限时间内获得所要求的输出。算法的优劣可以用空间复杂度与时间复杂度来衡量。
一百减一是零
2024/07/25
1300
Java实现常见的排序算法
本文简单说下排序算法,比较常见的排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。
Jensen_97
2023/07/20
2450
Java实现常见的排序算法
快速排序法及优化
快速排序 快排是目前平均时间复杂度最小的排序法。体现了分治的思想。算法比较经典,因此在这里记录一下,加深印象。 快速排序中比较核心的是要寻找一个pivot值。即枢轴值。 核心思想就是,将需要排序的数列,以pivot值为中心,以大小左右分开。然后对左右两段数组再重新选取pivot值。以此递归。 下面我们来看一看代码。 public class QuickSortManager { int pivotloc; public void quickSort(int[] arr , int low ,
Oceanlong
2018/07/03
5910
一文带你读懂排序算法(五):快速排序算法
快速排序算法是一种非常高效的排序算法,它采用“分而治之”的思想,将大的拆分为小的,小的拆分为更小的。
后台技术汇
2022/05/28
7260
一文带你读懂排序算法(五):快速排序算法
排序算法的 Python 实现以及时间复杂度分析
我用 Python 实现了冒泡排序、选择排序、插入排序、归并排序、快速排序。然后简单讲了讲快速排序的优化,我们可以通过小数组采用插入排序来减少递归的开销;对于有一定顺序的数组,我采用三数取中来提高性能;对于包含大量重复数的数组,我用了三路快速排序来提高性能。 最后,我把这些排序算法应用在随机数组、升序数组、降序数组、包含大量重复数的数组上,比较了一下它们的耗时。
马修
2021/01/21
1.7K0
排序算法的 Python 实现以及时间复杂度分析
[数据结构] 万字解析排序算法
快速排序(Quick Sort)是一种高效的排序算法,它利用分治法将一个数组分成两个子数组,然后递归地对这两个子数组进行排序。在快速排序的每一趟排序中,核心步骤是单趟循环,这一步骤将数组分成两分,一部分的所有元素都小于等于一个特定的“基准值”(pivot),另一部分的所有元素都大于基准值。
DevKevin
2024/08/09
1340
[数据结构] 万字解析排序算法
【排序算法】实现快速排序(霍尔法&&三指针法&&挖坑法&&优化随即选key&&中位数法&&小区间法&&非递归版本)
快速排序是一种分治算法。它通过一趟排序将数据分割成独立的两部分,然后再分别对这两部分数据进行快速排序。
学习起来吧
2024/03/24
5060
【排序算法】实现快速排序(霍尔法&&三指针法&&挖坑法&&优化随即选key&&中位数法&&小区间法&&非递归版本)
交换排序—快速排序(Quick Sort)
2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。
瑾诺学长
2018/09/21
3860
交换排序—快速排序(Quick Sort)
快速排序的优化思路
在对快速排序进行优化前,先让我们回顾一些快速排序的思想: 快速排序就是分而治之思想的体现,将有序序列分成对立的两部分,一部分值都比关键字值小,一部分值都比关键字值大,再分别对两部分进行排序 对快速排序不了解的可以先看看快速排序的具体过程和代码讲解 下面来看代码:
大忽悠爱学习
2021/11/15
3520
快速排序解读(基于java实现)
快速排序(Quicksort)是一种常用的排序算法,其原理基于分治策略。它的基本思想是选择一个基准元素,通过一趟排序将待排序的元素分割成独立的两部分,其中一部分的所有元素都小于基准,另一部分的所有元素都大于基准,然后对这两部分继续进行排序,直到整个序列有序。
一个风轻云淡
2023/12/17
2570
快速排序的新用法
快速排序是一种高效的排序算法,利用分治的思想进行排序。它的基本原理是在待排序的n个数据中任取一个数据为分区标准,把所有小于该排序码的数据移到左边,把所有大于该排序码的数据移到右边,中间放所选记录,称之为一趟排序。然后,对前后两个子序列重复上述过程,直到所有记录都排好序。通俗点说,大致过程是对于一个无序序列,找到一个"哨兵数",将序列中所有比哨兵数小的数字都移在哨兵数的左边,所有比哨兵数大的数字都移在哨兵数的右边;然后分别对哨兵数左边和右边再使用同样的方法找到新的哨兵数,并再次进行分类,直到集合不可分割为止。
人不走空
2024/02/20
1380
排序算法之冒泡、插入、快排和选择排序
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
海仔
2019/10/28
3380
深入了解快速排序:原理、性能分析与 Java 实现
快速排序(Quick Sort)是一种经典的、高效的排序算法,被广泛应用于计算机科学和软件开发领域。本文将深入探讨快速排序的工作原理、步骤以及其在不同情况下的性能表现。
修己xj
2023/10/08
2.6K0
深入了解快速排序:原理、性能分析与 Java 实现
算法学习:快速排序
这是算法流程的起点,从数列中精心挑选出一个元素,赋予它一个特殊角色——“基准”(pivot)。基准的选择可以很灵活,但理想情况下应倾向于选择一个能将数据集大致均匀分割的值,以促进算法效率。
空白诗
2024/06/14
1910
算法学习:快速排序
八十一、最快最优的快速排序和优化
不久前,我在牛客中看到这样一个笑话,面试官让他写一个快速排序,结果他写了一个冒泡排序,虽说不是计算机专业的,还一直说没有写错,都不知道面试官为什么这么PASS。其实,一共有十大排序算法,最快最稳定的就是快速排序,简称快排。
润森
2022/08/17
6810
八十一、最快最优的快速排序和优化
【金九银十】笔试通关 + 小学生都能学会的快速排序
快速排序(Quick Sort)是一种高效的排序算法,采用分治法(Divide and Conquer)策略来对数组进行排序。它的核心思想是通过一趟排序将待排序的数组分成两部分,其中一部分的所有元素比另一部分的所有元素都要小,然后递归地对这两部分分别进行快速排序,直到整个序列有序。
不惑
2024/09/10
1810
【金九银十】笔试通关 + 小学生都能学会的快速排序
相关推荐
十种排序方法
更多 >
目录
  • 快速排序的思想
  • 时间复杂度
  • 实现
  • 优化方法
  • 选择更好的基准值:
  • 示例代码优化
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档