快速排序——浙大《数据结构》学习笔记

1.概述

大一学生第一篇博客,记录下自己看网课的心得,文中有错误或是不足的地方还请指出。


2.算法简介

快速排序(英语:Quicksort),又称划分交换排序,简称快排,一种排序算法,最早由东尼·霍尔提出。在平均状况下,排序 n个项目要O(nlog n)(大O符号)次比较。在最坏状况下则需要 O(n2)次比较,但这种状况并不常见。事实上,快速排序 O(nlog n)通常明显比其他算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地达成。


3.算法实现

快速排序采用了一种分而治之的思想, 将数组分为三部分:pivot,比pivot小的数和比pivot大的数,其中pivot是从数组A中选的一个主元。算法的伪代码如下:

void quick_sort(int *a, int n)
{
        
      if ( N < 2 )
	        return; 
			
	  pivot = 从a中选一个主元;
	  将 S = {
    a \ pivot } 分成2个独立子集: 
	  a1 = {
    b | b <= pivot } 和 
	  a2 = {
    b | b >= pivot }; 
	  a = quick_sort(a1,n1)
		            {
   pivot}
		  quick_sort(a2,n2);
}

  可以看到,整个算法的排序步骤就是划分子集后进行递归排序。

3.1.选主元

· 如果令 pivot = a[0]
在传统的快速排序中,往往选择头元素作为pivot,但是这样在数组基本有序的情况会出现很多次没有用处的比较。下面是一个已经有序的数组:我们可以看到的是
算法首先将1和后面的元素分成两部分:
  1 2 3 4 5 6 ··· N-1 N
&再将2和后面的元素分成两部分:
     2 3 4 5 6 ··· N-1 N
再将3和后面的元素分成两部分:
        3 4 5 6 ··· N-1 N
           ······
上述的过程用时间复杂度表示如下:
T ( N ) = O( N ) + T ( N–1 )
      = O( N ) + O ( N–1 ) + T( N–2 )
      = O( N ) + O ( N–1 ) + ··· + O( 1 )
      = O( N2 )

· 若使用rand()函数随机取pivot
采用此种方法会直接调库,相比于在数组中选择一个数字,调库更容易返回一个大于或小于数组中所有元素的值。这样的话,时间开销太大,十分浪费内存,显然不是最优解。

· 分别取头尾和中间的数,取其中位数作为pivot的值
例如8、12、3的中位数就是8,就使用8作为pivot,下面我们来看看代码

int median3(int *a, int left, int right) {
   
    int center = left + (right - left) / 2;  // Use this form to prevent overflow
    if (a[left] > a[center]) {
   
        swap(a, left, center);
    }
    if (a[left] > a[right]) {
   
        swap(a, left, right);
    }
    if (a[center] > a[right]) {
   
        swap(a, center, right);
    }
    // In this time, a[left] <= a[center] <= a[right]
    // Hide the pivot on the position of right-1
    swap(a, center, right - 1);
    return a[right - 1];
}

在第3行代码中,采用了防止溢出的形式;
第4~7行代码,将最小值交换到了 a[left];
第8~9行代码,确定了剩下两个元素的次序。
这时我们将

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值