【快速排序算法】原理讲解+代码实现

原理:

快速排序(Quick Sort)是一种高效的排序算法,它基于“分治法”(Divide and Conquer)的思想。快速排序通过将待排序的数组分成较小的子数组,然后递归地对子数组进行排序,最终将它们合并成有序的数组。

步骤概括如下:

  1. 选择基准元素: 从待排序的数组中选择一个元素作为基准元素。通常选择数组的第一个元素作为基准元素,但也可以选择最后一个元素或者随机选择一个元素作为基准元素。

  2. 划分操作: 将数组中的元素分为两部分,使得左边的元素都小于或等于基准元素,右边的元素都大于或等于基准元素。这个过程称为划分(Partition)操作。划分的目的是将前面选定的基准元素放在它最终应该出现的位置上。

  3. 递归排序: 对划分后的两个子数组分别进行快速排序。递归地重复以上步骤,直到每个子数组只包含一个元素,此时整个数组已经有序。

  4. 合并结果: 将排序后的子数组合并成一个有序的数组。

示例:

假设一个待排序数组:[5, 2, 9, 3, 7, 1, 8, 4]

  1. 选择基准元素:这里选择第一个元素5作为基准。

  2. 划分操作:将数组划分为[2, 3, 1, 4](小于5的部分)和[9, 7, 8](大于5的部分),基准元素5现在在正确的位置上。

  3. 递归排序:对划分后的两个子数组进行快速排序。

    • 对[2, 3, 1, 4]进行快速排序,选择基准元素2,划分为[1]和[3, 4],再对子数组[3, 4]进行快速排序,最终得到[1, 2, 3, 4]。
    • 对[9, 7, 8]进行快速排序,选择基准元素9,划分为[7, 8],再对子数组[7, 8]进行快速排序,最终得到[7, 8, 9]。
  4. 合并结果:将排序后的子数组合并为最终的有序数组[1, 2, 3, 4, 5, 7, 8, 9]。

C++代码实现快速排序:

#include 
using namespace std;

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int left = l, right = r;
    int temp = q[left];

    while (left < right)
    {
        while (q[right] >= temp && left < right) {
            right--;
        }
        if (left < right) {
            q[left] = q[right];
            left++;
        }
        while (q[left] < temp && left < right) {
            left++;
        }
        if (left < right) {
            q[right] = q[left];
            right--;
        }
 
    }
    q[left] = temp;

    quick_sort(q, l, left-1);
    quick_sort(q, left + 1, r);
}


int main()
{
    int arr[] = { 2,4,1,3,6,9,7,5 };
    cout << "排序前:" << endl;
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
    int a = 0, b = sizeof(arr) / sizeof(arr[0]) - 1;
    quick_sort(arr, a, b);

    cout << "排序后:" << endl;
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
        cout << arr[i] << " ";
    }

    return 0;
}

运行结果截图:

【快速排序算法】原理讲解+代码实现_第1张图片

 

时间复杂度:

快速排序的时间复杂度主要取决于两个因素:划分操作和递归调用。

  1. 划分操作: 在划分操作中,我们需要对数组进行遍历以找到基准元素的正确位置。在最坏情况下,数组已经有序或基本有序时,每次划分可能只减少一个元素的区间大小,导致划分过程变得非常慢。因此,最坏情况下的划分操作的时间复杂度为O(n),其中n是待排序数组的元素个数。

  2. 递归调用: 在每次递归调用时,问题规模减少一半,即处理的子数组大小为原数组的一半。递归调用的次数取决于数组的划分情况,最坏情况下需要进行O(n)次递归调用。

由于快速排序是一个递归算法,我们需要考虑所有递归调用的时间复杂度。因此,快速排序的平均时间复杂度为O(nlogn),最坏情况下为O(n^2)。

最坏情况:

原本需要排序的数组已经有序,如果使用快速排序算法,则时间复杂度直接退化为O(n^2)。

空间复杂度:

快速排序的空间复杂度主要取决于递归调用过程中的栈空间。在最坏情况下,递归调用可能会达到O(n)层,每层需要O(1)的空间来存储局部变量。因此,在最坏情况下,快速排序的空间复杂度为O(n)。

需要注意的是,快速排序通常是一个原地排序算法,它不需要额外的存储空间来存储临时数据。但由于递归调用过程中需要使用栈空间,所以在最坏情况下,空间复杂度为O(n)。

综上所述,该快速排序算法的平均时间复杂度为O(nlogn),最坏情况下的时间复杂度为O(n^2),而空间复杂度为O(n)。

你可能感兴趣的:(c++,数据结构,算法,排序算法)