C++快速排序的分析与优化详解

C++快速排序的分析与优化详解

前言

快速排序是一种高效的排序算法,它的时间复杂度为 $O(nlogn)$,但是在某些情况下,快排的时间复杂度会退化,导致排序时间变长。本文将对快速排序的原理、实现、优化等方面进行详细分析,帮助读者更好地理解和实现快速排序算法。

原理

快速排序的原理是基于分治法。首先从数列当中挑出一个元素,称为基准(pivot)。接着将数列中小于基准的元素移动到基准的左侧,大于基准的元素移动到基准的右侧,这样就将数列分成了两个部分。然后对左右两个部分递归地进行快速排序,直到整个数列有序为止。

实现

以下是使用 C++ 实现的快速排序的代码:

void quick_sort(vector<int>& nums, int left, int right) {
    if (left < right) {
        int i = left, j = right, x = nums[left];
        while (i < j) {
            while (i < j && nums[j] > x) j--;
            if (i < j) nums[i++] = nums[j];
            while (i < j && nums[i] < x) i++;
            if (i < j) nums[j--] = nums[i];
        }
        nums[i] = x;
        quick_sort(nums, left, i - 1);
        quick_sort(nums, i + 1, right);
    }
}

函数的参数包括一个整数数组和需要排序的区间范围。算法的主要流程是对基准元素进行一次划分,然后递归地对左右两侧继续执行快速排序。

优化

优化1 - 随机化选择基准

快速排序的效率取决于基准的选择,最理想的情况是每次选择的基准元素都能将数列分成两个部分,但是如果每次选择的基准都是数列的最大或最小值,那么快速排序的时间复杂度将会退化到 $O(n^2)$。因此可以提出一个优化方案,即在每次排序前随机选择一个数作为基准元素,这样可以降低最坏情况的出现概率。

以下是优化后的代码:

void quick_sort(vector<int>& nums, int left, int right) {
    if (left < right) {
        int i = left, j = right;
        // 随机选择一个数作为基准元素
        int idx = rand() % (right - left + 1) + left;
        swap(nums[idx], nums[left]);
        int x = nums[left];
        while (i < j) {
            while (i < j && nums[j] > x) j--;
            if (i < j) nums[i++] = nums[j];
            while (i < j && nums[i] < x) i++;
            if (i < j) nums[j--] = nums[i];
        }
        nums[i] = x;
        quick_sort(nums, left, i - 1);
        quick_sort(nums, i + 1, right);
    }
}

优化2 - 三数中值分割法

选择基准元素时,如果每次都选择左侧第一个元素,那么可能会出现最坏情况。为了避免这种情况,可以使用三数中值分割法,在排序区间的左、右、中三个位置分别取一个数,选取其中的中值作为基准元素。

int mid = (left + right) / 2;
if (nums[mid] > nums[right])
    swap(nums[mid], nums[right]);
if (nums[left] > nums[right])
    swap(nums[left], nums[right]);
if (nums[mid] > nums[left])
    swap(nums[mid], nums[left]);
int x = nums[left];

优化后的排序代码:

void quick_sort(vector<int>& nums, int left, int right) {
    if (left < right) {
        int i = left, j = right;
        // 三数中值分割法选择基准元素
        int mid = (left + right) / 2;
        if (nums[mid] > nums[right])
            swap(nums[mid], nums[right]);
        if (nums[left] > nums[right])
            swap(nums[left], nums[right]);
        if (nums[mid] > nums[left])
            swap(nums[mid], nums[left]);
        int x = nums[left];
        while (i < j) {
            while (i < j && nums[j] > x) j--;
            if (i < j) nums[i++] = nums[j];
            while (i < j && nums[i] < x) i++;
            if (i < j) nums[j--] = nums[i];
        }
        nums[i] = x;
        quick_sort(nums, left, i - 1);
        quick_sort(nums, i + 1, right);
    }
}

示例

示例1 - 普通快速排序

vector<int> nums = { 5, 3, 6, 4, 1, 2 };
int n = nums.size();
quick_sort(nums, 0, n - 1);
for (int i = 0; i < n; i++) {
    cout << nums[i] << " ";
}

输出结果:

1 2 3 4 5 6

示例2 - 随机化快速排序

vector<int> nums = { 5, 3, 6, 4, 1, 2 };
int n = nums.size();
srand(time(NULL));
quick_sort(nums, 0, n - 1);
for (int i = 0; i < n; i++) {
    cout << nums[i] << " ";
}

输出结果:

1 2 3 4 5 6

总结

本文主要介绍了快速排序的原理、实现和优化方案,并给出了两个示例。快速排序是一种高效的排序算法,但是在实际应用中需要注意最坏情况的出现,可以通过随机化选择基准和使用三数中值分割法来降低出现最坏情况的概率,从而提高算法的性能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++快速排序的分析与优化详解 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • c++中八大排序算法

    c++中八大排序算法 本文介绍的是C++中八大排序算法,分别是冒泡排序、选择排序、插入排序、快速排序、希尔排序、归并排序、堆排序和计数排序。下面将对这八种算法进行详细讲解。 冒泡排序 冒泡排序(Bubble Sort),是一种简单的排序算法。它重复地遍历要排序的列表,比较每对相邻的项,如果它们的顺序错误就把它们交换过来。遍历列表的工作是重复地进行知道没有再需…

    算法与数据结构 2023年5月19日
    00
  • JavaScript数据结构与算法之基本排序算法定义与效率比较【冒泡、选择、插入排序】

    JavaScript数据结构与算法之基本排序算法定义与效率比较 概述 排序是计算机科学中最常见的操作之一,是将数据按照一定的顺序重新排列的过程。排序算法被广泛应用于搜索、数据压缩、数据库等领域。JavaScript中常用的基本排序算法有3种:冒泡排序、选择排序和插入排序。本文将详细介绍这三种算法的原理、JavaScript实现以及时间复杂度比较。 冒泡排序 …

    算法与数据结构 2023年5月19日
    00
  • 如何利用Python动态展示排序算法

    首先,我们需要了解一下Python中常用的用于动态展示的库——matplotlib和pygame。 matplotlib是一个数据可视化库,它可以让我们轻松地创建各种静态和动态的图形,包括折线图、柱形图等等,而pygame则是一个开源的游戏开发库,它专用于创建游戏和动态图形。 接下来,我们就可以使用这两个库来展示排序算法了。 下面是一个示例,展示了如何使用m…

    算法与数据结构 2023年5月19日
    00
  • C/C++实现双路快速排序算法原理

    作为网站的作者,我很愿意为大家详细介绍C/C++实现双路快速排序算法原理。下面是详细的攻略,分为以下几个部分: 1. 什么是双路快排算法 双路快排(Dual-Pivot Quick Sort)算法是一种高效的排序算法。该算法是快速排序(Quick Sort)的一种改进。 双路快排算法的基本思想是:选取两个基准值(pivot)来进行排序,将数组划分为三部分:小…

    算法与数据结构 2023年5月19日
    00
  • 算法系列15天速成 第一天 七大经典排序【上】

    我会为你详细讲解“算法系列15天速成 第一天 七大经典排序【上】”的完整攻略。 标题 算法系列15天速成 第一天 七大经典排序【上】 内容 本文主要介绍了常用的七大经典排序算法,分别是插入排序、希尔排序、选择排序、冒泡排序、快速排序、归并排序以及堆排序。对每个算法的特点、实现过程和时间复杂度进行了详细的讲解,同时也对每个算法进行了简单的示例说明。 插入排序 …

    算法与数据结构 2023年5月19日
    00
  • python KNN算法实现鸢尾花数据集分类

    Python实现KNN算法对鸢尾花数据集进行分类 介绍 KNN(K-Nearest-Neighbor)算法是一种非常常用且简单的分类算法之一。它的基本思想是把未知数据的标签与训练集中最邻近的K个数据的标签相比较,得票最多的标签就是未知数据的标签。本文将介绍如何使用Python实现对鸢尾花数据集进行KNN分类。 步骤 加载数据 首先,我们需要加载鸢尾花数据集。…

    算法与数据结构 2023年5月19日
    00
  • 人脸检测中AdaBoost算法详解

    人脸检测中AdaBoost算法详解 什么是AdaBoost算法? AdaBoost(Adaptive Boosting,自适应增强算法)是一种分类算法,它可以将若干个弱分类器组合起来形成一个强分类器,以提高分类的准确率和鲁棒性。AdaBoost最初用于人脸识别领域,在实际应用中具有良好的效果。 AdaBoost分类器是如何工作的? AdaBoost分类器是基…

    算法与数据结构 2023年5月19日
    00
  • C++递归实现选择排序算法

    实现选择排序算法的递归版本,步骤如下: 步骤1:找到最小值 首先,在要排序的数组中找到最小值,这个过程可以用for循环来实现。具体实现如下: // 找到数组中最小值的下标 int findMinIndex(int arr[], int startIndex, int endIndex) { int minIndex = startIndex; for (in…

    算法与数据结构 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部