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日

相关文章

  • Javascript排序算法之合并排序(归并排序)的2个例子

    下面我将详细讲解“Javascript排序算法之合并排序(归并排序)的2个例子”的完整攻略。该攻略包含以下内容: 合并排序算法的原理介绍 归并排序实现流程 两个例子的具体实现及演示 合并排序算法的原理介绍 合并排序是一种基于分治思想的排序算法。它的基本思路是将待排序序列分成若干个子序列,对每个子序列递归地进行排序,最后合并所有子序列,得到最终的排序结果。 具…

    算法与数据结构 2023年5月19日
    00
  • JS使用队列对数组排列,基数排序算法示例

    JS使用队列对数组进行排序,可以使用基数排序算法。 基数排序算法是一种非比较排序算法,通过将待排序数据按照位数切割成个、十、百、千等位,然后从低位依次向高位对每个位数进行排序。基数排序算法在排序过程中使用了队列数据结构来保存临时排序结果。 以下是基数排序算法的JavaScript实现: function radixSort(array) { const ma…

    算法与数据结构 2023年5月19日
    00
  • golang 归并排序,快速排序,堆排序的实现

    Golang 实现归并排序,快速排序和堆排序 简介 排序算法的实现是大多数程序员必备的技能之一。在这个过程中,我们考虑三种经典的排序算法之一:归并排序,快速排序和堆排序。我们在学习它们的同时,也在学习使用 Golang 写出高效的排序算法。 归并排序 算法原理 归并排序是基于归并操作的一种排序算法,该算法的核心思想是将一个数组分成两个较小的数组,然后递归地将…

    算法与数据结构 2023年5月19日
    00
  • C++中字符串全排列算法及next_permutation原理详解

    C++中字符串全排列算法及next_permutation原理详解 介绍 全排列是指将一组数按一定顺序进行排列,得到所有有可能的组合。例如,对于数字1、2、3,全排列如下: 123132213231312321 C++中有现成的函数next_permutation可以实现全排列,但理解其原理仍然很重要,本篇文章将详细讲解next_permutation的原理…

    算法与数据结构 2023年5月19日
    00
  • PHP排序算法类实例

    让我先给出该攻略的大纲: 算法类的设计思路 冒泡排序算法示例 快速排序算法示例 使用算法类进行排序 接下来,我将详细讲解每一步内容。 1. 算法类的设计思路 首先,我们需要为排序算法创建一个类,这个类应该包含常见排序算法的实现函数。这些函数应该是静态函数,以便我们可以直接访问它们,而不必实例化排序类。 我们还需要实现一些通用的辅助函数,这些函数可以在算法函数…

    算法与数据结构 2023年5月19日
    00
  • PHP rsa加密解密算法原理解析

    PHP RSA加密解密算法原理解析 RSA是一种非对称加密算法,它使用两个密钥:公钥和私钥。公钥可以向外公开,用于加密数据;而私钥只由数据的持有者保管,用于解密数据。在本文中,我们会使用PHP实现RSA加密解密算法,并分享一些示例代码。 RSA加密解密算法原理 RSA加密解密算法的原理主要是基于数学中的大数分解问题和欧拉定理。以下是RSA算法的一般流程: 用…

    算法与数据结构 2023年5月19日
    00
  • 可能是你看过最全的十大排序算法详解(完整版代码)

    针对“可能是你看过最全的十大排序算法详解(完整版代码)”这篇文章,下面是详细的攻略: 标题 首先,该文章的标题是:可能是你看过最全的十大排序算法详解(完整版代码) 文章简介 其次,在文章简介中,作者提到该篇文章是一个完整介绍了十大排序算法并且附有代码实现的文章,可以帮助读者了解这些排序算法的原理和代码实现。 内容 文章的主体部分是对十大排序算法进行详细的讲解…

    算法与数据结构 2023年5月19日
    00
  • c++插入排序详解

    c++插入排序详解 1. 插入排序算法介绍 插入排序法是一种简单直观的排序方法。它的基本思路是通过每次将一个待排序的元素按照其大小插入到已经排好序的一组元素中,直到全部元素插入完毕,即排序完毕。 在实际应用中,对于较小的数据集,插入排序通常比快速排序和归并排序等复杂度为O(nlogn)的算法执行效率更高。 2. 插入排序算法的实现 下面给出一个C++实现的插…

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