排序算法——快速排序

本文介绍快速排序算法原理及其C语言实现过程。快速排序采用分治法将数列分成两部分,并递归排序。文章提供了一个完整的代码示例,展示如何通过基准元素进行分割,最终达到整个序列有序。

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。

步骤为:

1.从数列中挑出一个元素,称为 "基准"(pivot),
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,该基准是它的最后位置。这个称为分割(partition)操作。
3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

最坏时间复杂度: O(n^2),平均时间复杂度:O(nlogn)
快速排序是不稳定的排序算法。

Code:
  1. #include <stdio.h>   
  2.   
  3. void swap(int *a, int *b)   
  4. {   
  5.     int temp = *a;   
  6.     *a = *b;   
  7.     *b = temp;   
  8. }   
  9.   
  10. int partition(int a[], int p, int q)   
  11. {   
  12.     int x, i, j;   
  13.   
  14.     x = a[p];/* x as a pivot */  
  15.     i = p;   
  16.     for (j = p + 1; j < q; j++) {   
  17.         if (a[j] <= x) {   
  18.             i++;   
  19.             swap(&a[i], &a[j]);   
  20.         }   
  21.     }   
  22.     swap(&a[p], &a[i]);   
  23.     return i;   
  24. }   
  25.   
  26. void quick_sort(int a[], int p, int q)   
  27. {   
  28.     if (p < q) {   
  29.         int r = partition(a, p, q);   
  30.         quick_sort(a, p, r);  /* sort sub list a[p, r)  */  
  31.         quick_sort(a, r+1, q);/* sort sub list a[r+1,q) */  
  32.     }   
  33.   
  34. }   
  35.   
  36. int main()   
  37. {   
  38.     int a[] = {6, 10, 13, 5, 8, 3, 2, 11}, i;   
  39.     int size = sizeof(a) / sizeof(int);   
  40.     quick_sort(a, 0, size);   
  41.   
  42.     for (i = 0; i < size; i++)   
  43.         printf("%d ", a[i]);   
  44.     return 0;   
  45. }  

如果我们调用的是quick_sort(a, 0, size - 1),那么要做以下修改
code 16:j <= q
code 30:quick_sort(a, p, r-1)
code 31:quick_sort(a, r+1, q)

### 快速排序分治算法实现与原理 快速排序是一种基于分治策略的经典排序算法,其核心思想是通过选取一个基准值(Pivot),将待排序数组划分为两个子数组,使得左侧子数组的元素均不大于基准值,右侧子数组的元素均不小于基准值。随后递归地对这两个子数组进行相同的操作,直到每个子数组只有一个元素或为空为止。 #### 1. 快速排序的核心思想 快速排序的关键在于如何有效地划分数组以及递归处理子数组的过程。具体来说,快速排序可以分解为以下几个阶段[^2]: - **选择基准值 (Pivot)**:通常可以选择第一个元素、最后一个元素或者随机选择某个元素作为基准值。 - **分区操作 (Partition)**:重新排列数组,使所有小于基准值的元素位于左边,所有大于基准值的元素位于右边,并返回基准值的位置索引。 - **递归排序**:对基准值两侧的子数组分别递归应用相同的分区和排序逻辑。 最终的结果是,当所有的子数组都被排序完成后,整个数组也变得有序。 #### 2. 时间复杂度分析 快速排序的时间性能取决于每次分割后的子数组大小分布情况。理想情况下,如果每次都能均匀地将数组一分为二,则时间复杂度为 \( O(N \log N) \)[^4]。然而,在最坏的情况下(例如输入数组已经完全逆序或顺序排列),可能会退化至线性平方级的时间复杂度 \( O(N^2) \)。 #### 3. 空间复杂度 由于快速排序采用的是原地排序方式,因此不需要额外分配大量的存储空间来保存临时副本。除了用于记录递归调用栈的空间外,几乎无需其他辅助内存资源消耗。对于平均情况而言,递归深度大约为 \( \log N \),故总体空间复杂度接近于 \( O(\log N) \)[^2]。 #### 4. Python 实现代码示例 以下是使用Python编写的快速排序函数的一个简单版本: ```python def quick_sort(arr): if len(arr) <= 1: return arr else: pivot = arr[len(arr)//2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return quick_sort(left) + middle + quick_sort(right) # 测试例子 example_array = [3,6,8,10,1,2,1] print("Sorted array:", quick_sort(example_array)) ``` 此段程序展示了基本的功能框架,实际工程环境中可能还需要考虑更多边界条件及优化措施。 #### 5. 不稳定性的讨论 值得注意的一点是,尽管快速排序效率很高,但它并非总是稳定的排序方法。所谓稳定性是指相等键值的数据项在排序之后能够保持原有的相对次序不变。而因为我们在上面给出的例子中直接丢弃了关于位置的信息,所以在某些特定场景下可能导致原本相邻重复数值被打散重组从而破坏原有秩序关系[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值