排序算法介绍(四)快速排序

0. 简介

快速排序(Quick Sort)是一种高效的排序算法,采用了分治的思想。它选择一个基准元素,通过一趟排序将待排序序列分割成独立的两部分,其中一部分的所有元素都比基准元素小,另一部分的所有元素都比基准元素大,然后再对这两部分继续进行排序,以达到整个序列有序。


1. 快速排序的实现

快速排序的基本思想:

  1. 选择一个基准元素(pivot),通常选择序列的第一个元素。
  2. 将序列中所有比基准元素小的元素放在它的左边,所有比基准元素大的元素放在它的右边。这个过程称为"分区"(Partitioning)。
  3. 对基准元素的左边和右边的两个子序列分别进行快速排序。
  4. 递归地进行以上步骤,直到所有子序列的长度为1,即整个序列有序。

快速排序过程演示:


2. 快速排序时空间复杂度分析

常见情况下的时间复杂度和空间复杂度分析:

  1. 时间复杂度:

    • 平均情况:快速排序的平均时间复杂度为 O(n log n),其中 n 是待排序数组的长度。这是因为每次分区操作都能将数组分成大致相等的两部分,使得递归的深度为 log n,而每次分区操作的时间复杂度为 O(n)。
    • 最好情况:当输入数组已经有序或者接近有序时,快速排序的时间复杂度可以达到 O(n log n)。这是因为在这种情况下,每次分区操作都能将数组分成大小相等的两部分,使得递归的深度最小。
    • 最坏情况:当输入数组完全逆序或者存在大量重复元素时,快速排序的时间复杂度会退化为 O(n^2)。这是因为在这种情况下,每次分区操作只能将基准元素与一个元素进行交换,导致递归的深度达到最大。
  2. 空间复杂度:

    • 快速排序是一种原地排序算法,它的空间复杂度是 O(log n)。这是因为快速排序使用递归来实现,而递归需要使用栈来保存函数调用的上下文信息。在平均情况下,递归的深度为 log n,所以空间复杂度为 O(log n)。

以上分析是基于常见的快速排序实现方式,实际应用中可能会根据具体情况进行优化,从而改变时间复杂度和空间复杂度的性质。


3. 快速排序C语言代码

C代码实现:

cpp 复制代码
#include <stdio.h>  
  
void swap(int* a, int* b) {  
    int t = *a;  
    *a = *b;  
    *b = t;  
}  
  
int partition(int array[], int low, int high) {  
    int pivot = array[low];    // 基准元素  
    while (low < high) {  
        // 从后往前找到第一个小于基准元素的元素  
        while (low < high && array[high] >= pivot) {  
            high--;  
        }  
        array[low] = array[high];  // 将这个元素放到左边  
  
        // 从前往后找到第一个大于基准元素的元素  
        while (low < high && array[low] <= pivot) {  
            low++;  
        }  
        array[high] = array[low];  // 将这个元素放到右边  
    }  
    array[low] = pivot;  // 基准元素归位  
    return low;  // 返回基准元素的位置  
}  
  
void quickSort(int array[], int low, int high) {  
    if (low < high) {  
        int pi = partition(array, low, high);  // 获取基准元素位置  
        quickSort(array, low, pi - 1);  // 对基准元素左边的子序列进行递归排序  
        quickSort(array, pi + 1, high);  // 对基准元素右边的子序列进行递归排序  
    }  
}  
  
int main() {  
    int data[] = {8, 7, 2, 1, 0, 9, 6};  // 待排序的数组  
    int n = sizeof(data) / sizeof(data[0]);  // 数组长度  
    quickSort(data, 0, n - 1);  // 快速排序  
    printf("Sorted array in ascending order: \n");  
    for (int i = 0; i < n; ++i) {  
        printf("%d ", data[i]);  // 输出排序后的数组  
    }  
    return 0;  
}

代码解释:

  1. swap 函数用于交换两个整数的值。
  2. partition 函数是快速排序的核心部分,它实现了对待排序数组的分割。函数首先选取数组的第一个元素作为基准元素,然后从数组的末尾开始向前寻找第一个小于基准元素的元素,再从数组的开头开始向后寻找第一个大于基准元素的元素,然后交换这两个元素的位置。这个过程会一直重复,直到两个指针相遇。相遇时的位置就是基准元素应该放置的位置。此时,基准元素左边的所有元素都小于它,右边的所有元素都大于它。最后返回基准元素的位置。
  3. quickSort 函数是一个递归函数,它首先调用 partition 函数获取基准元素的位置,然后分别对基准元素的左右两边的子序列进行递归排序。递归的结束条件是子序列的长度小于等于1,也就是子序列已经是有序的。

4. 快速排序代码运行结果

代码运行结果:

相关推荐
Bt年18 分钟前
第十六届蓝桥杯 C/C++ B组 题解
c语言·c++·蓝桥杯
Tisfy1 小时前
LeetCode 1295.统计位数为偶数的数字:模拟
算法·leetcode·题解
禺垣1 小时前
GBDT算法原理及Python实现
人工智能·python·算法·机器学习·数据挖掘·集成学习
jiunian_cn2 小时前
【c++】【STL】list详解
数据结构·c++·windows·list·visual studio
虾球xz2 小时前
游戏引擎学习第250天:# 清理DEBUG GUID
c++·学习·游戏引擎
我命由我123452 小时前
STM32 开发 - stm32f10x.h 头文件(内存映射、寄存器结构体与宏、寄存器位定义、实现点灯案例)
c语言·开发语言·c++·stm32·单片机·嵌入式硬件·嵌入式
xyd陈宇阳2 小时前
嵌入式开发高频面试题全解析:从基础编程到内存操作核心知识点实战
c语言·数据结构·stm32·算法·面试
淋过很多场雨3 小时前
现代c++获取linux所有的网络接口名称
java·linux·c++
刘 大 望3 小时前
Java写数据结构:队列
java·数据结构·intellij-idea
__lost4 小时前
MATLAB退火算法和遗传算法解决旅行商问题
开发语言·算法·matlab·遗传算法·退火算法