排序算法系列之快速排序

快速排序

1 基本原理

核心思想:快速排序是一种 划分交换排序 ,其采用分治的策略思想 。
算法思路:
1. 首先从待排序序列中随机取出一个数作为基准数。
2. 分区过程,将比基准数大的数全放到它的右边,小于或等于基准数的数全放到它的左边。
3. 对左右区间重复第二步,直到各区间只有一个数。

2 实例说明

如上图所示,参考《算法导论》中给出的示例,对快速排序进行算法演示,待排序序列为A[2,8,7,1,3,5,6,4]:

  • 第一轮:将数组A分为两个子数组,左数组中数均小于等于基准数,右数组中数均大于基准数。具体步骤如下:
    1. 数组中选择一数为基准数,此处选择尾数4为基准数(建议随机选择)
    2. 选择参数 i, j来决定两个子数组如何划分。
    3. 从数组第一位开始,依次与基准数进行比较,若小于等于4,i与j均右移一位,反之i不动,j右移一位。如此A[0,i]均小于等于4,A[i+1,j]均大于4。
    4. 参考图例,a)中,2<4,i和j均右移一位;b)8>4,i不变,j右移;到了h),A[0,i]均小于等于4,A[i+1,j]均大于4。
    5. 将基准数4交换至正确的位置,原数组被划分为左数组和右数组。
  • 第二轮:分别对左右子数组重复第一轮操作,直到各数组只剩一个元素。

3 代码实现

// 快速排序(C++)

void swap(int& a, int& b)
{
    int tmp = a;
    a = b;
    b = tmp;
}

int partition(vector<int> &vi, int low, int up)//划分数组,并返回基准数在数组中位置
{
    int pivot = vi[up];
    int i = low - 1;
    for (int j = low; j < up; j++)
    {
        if (vi[j] <= pivot)
        {
            i++;
            swap(vi[i], vi[j]);
        }
    }
    swap(vi[i + 1], vi[up]);
    return i + 1;
}


void quickSort(vector<int> &vi, int low, int up)
{
    if (low < up)
    {
        int mid = partition(vi, low, up);
        quickSort(vi, low, mid - 1);
        quickSort(vi, mid + 1, up);
    }
}

4 性能分析

  • 1 时间复杂度
    快速排序的时间性能取决于快速排序递归的深度,递归过程中,子序列越平衡,则性能越好
    (1)最优情况下时,递归过程形成的递归树是一课平衡树,快速排序算法的时间复杂度为O(nlogn)。
    (2)最坏情况下时,递归过程形成的递归树是一课斜树,快速排序算法的时间复杂度为O(n2)。
    (3)平均情况下,时间复杂度为O(nlogn)。
  • 2 空间复杂度
    就空间复杂度来说,主要是递归造成的栈空间的使用。
    (1)最好情况,递归树的深度为log2n,其空间复杂度也就为O(logn)。
    (2)最坏情况,需要进行n‐1递归调用,其空间复杂度为O(n)。
    (3)平均情况,空间复杂度也为O(logn)。
  • 3 算法稳定性
    快速排序在排序过程中,由于基准数的比较和交换是跳跃进行的,因此,快速排序是一种不稳定的排序算法

猜你喜欢

转载自blog.csdn.net/hlc246/article/details/81027033