本次笔记内容:
10.1.1 算法概述
10.1.2 选主元
10.1.3 子集划分
10.1.4 算法实现

文章目录

  • 算法概述
  • 选主元
  • 子集划分
    • 子集划分策略:遇到与pivot相等元素则交换
    • 小规模数据处理
  • 算法实现

算法概述

思想是“分而治之”,也是用递归手法实现。

如上图,选出一个数“65”,将大于其和小于其的部分分而治之,递归下去。

其伪码如上图。其主元、分为两个独立子集这两个步骤需要很好的设计,不然可能使快排事倍功半。

快排最好的情况:每次正好中分,T(N)=O(Nlog⁡2N)T(N)=O(N \log_2 N)T(N)=O(Nlog2​N)。

选主元

主元(pivot)的选择方法对运行效率影响很大。

比较常用的方法是:取头、中、尾3个位置的中位数。

ElementType Median3(ElementType A[], int Left, int Right)
{int Center = (Left + Right) / 2;if (A[Left] > A[Center])Swap(&A[Left], &A[Center]);if (A[Left] > A[Right])Swap(&A[Left], &A[Right]);if (A[Center] > A[Right])Swap(&A[Center], &A[Right]);// A[Left] <= A[Center] <= A[Right]Swap(&A[Center], &A[Right - 1]); // 将pivot藏到右边// 如此,子集划分时,便只需考虑A[Left+1]...A[Right]return A[Right - 1];
}

子集划分

上图为A[Left+1]…A[Right]与主元6。定义两个指针i、j指向如图位置。

如上图,先考虑i的8,8所在位置(被i所指)应该小于等于6,而8大于6,因此上面标注红色“>”;然后看j所指7,7大于等于6,正确(因为被j所指);然后移动j,看j指向的2,2小于6,不对,标红色“<”。

如上图,两边元素都被标注红色时,交换两元素位置(图中为2与8位置互换后的结果)。继续迭代。

如上图,当i越过了j,则停止。并且,将i所指(i所指位置应该为主元位置)跟主元6交换,则可得划分好子集。并对接下来的子集选主元、划分子集,如此递归。

快速排序块就快在:每一次扫描结束,主元就到了其最终位置上。

子集划分策略:遇到与pivot相等元素则交换

如果有元素等于pivot怎么办?

  • 如果停下来交换,则效率低(无用功多);
  • 但是,停下来交换让时间复杂度趋为O(Nlog⁡2N)O(N \log_2 N)O(Nlog2​N)(效率高),因为主元更容易被放在中间(i、j更有可能放在中间);
  • 如果不做处理,尽管没有无效交换,但是主元有可能最终被放到端点,时间复杂度可能为O(N2)O(N^2)O(N2)。

小规模数据处理

如上图,对于小规模数据,没有必要使用快速排序(递归占用空间大)。

因此设立一个阈值,小于Cutoff时,使用插入排序。

算法实现

void Quciksort(ElementType A[], int Left, int Right)
{if (Cutoff <= Right - Left){Pivot = Median3(A, Left, Right);i = Left;j = Right;for (;;){while (A[++i] < Pivot){}while (A[--j] > Pivot){}if (i < j)Swap(&A[i], &A[j]);elsebreak;}Swap(&A[i], &A[Right - 1]);Quciksort(A, Left, i - 1);Quciksort(A, i + 1, Right);}elseInsertion_Sort(A + Left, Right - Left + 1);
}

如上,但此时并没有一个很合适的函数接口,因此设立的一个友好的接口如下。

void Quick_Sort(ElementType A[], int N)
{Quciksort(A, 0, N - 1);
}

【数据结构笔记36】C实现:基于Median3的快速排序相关推荐

  1. SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

    数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...

  2. 数据结构笔记--线性表定义与实现(Swift)

    数据结构笔记系列 数据结构笔记-两个有序链表合并成一个有序链表 线性表   线性表是最常用且最简单的一种数据结构,简言之,一个线性表是 n 个数据元素的有序序列. 特点 只有一个首结点和尾结点: 除首 ...

  3. 数据结构笔记(王道考研) 第八章:排序

    大部分内容基于中国大学MOOC的2021考研数据结构课程所做的笔记,该课属于付费课程(不过盗版网盘资源也不难找...).后续又根据23年考研的大纲对内容做了一些调整,将二叉排序树和平衡二叉树的内容挪到 ...

  4. 数据结构笔记(王道考研) 第五章:树和二叉树

    大部分内容基于中国大学MOOC的2021考研数据结构课程所做的笔记,该课属于付费课程(不过盗版网盘资源也不难找...).后续又根据23年考研的大纲对内容做了一些调整,将二叉排序树和平衡二叉树的内容挪到 ...

  5. 【R】【课程笔记】02+03 基于R软件的计算

    本文是课程<数据科学与金融计算>第2-3章的学习笔记,主要介绍R语言在统计和机器学习中的应用,用于知识点总结和代码练习,Q&A为问题及解决方案,参考书籍为<R软件及其在金融定 ...

  6. 数据结构笔记(王道考研) 第一章:绪论

    大部分内容基于中国大学MOOC的2021考研数据结构课程所做的笔记,该课属于付费课程(不过盗版网盘资源也不难找...).后续又根据23年考研的大纲对内容做了一些调整,将二叉排序树和平衡二叉树的内容挪到 ...

  7. 数据结构笔记(王道考研) 第七章:查找

    大部分内容基于中国大学MOOC的2021考研数据结构课程所做的笔记,该课属于付费课程(不过盗版网盘资源也不难找...).后续又根据23年考研的大纲对内容做了一些调整,将二叉排序树和平衡二叉树的内容挪到 ...

  8. 48. 数据结构笔记之四十八的有向无环图的应用关键路径

    48. 数据结构笔记之四十八的有向无环图的应用关键路径 "富贵不淫贫贱乐 , 男儿到此是豪雄.-- 程颢" 来看下有向无环图的另一个应用关键路径. 1.  关键路径 与AOV-网相 ...

  9. 归并排序算法 C++实现与时间复杂度(考过)恋上数据结构笔记

    复习梗概 画图,自己整个数组,看代码写步骤,这个对理解归并排序还是很有必要的 合并两个有序数组的merge函数写法 时间复杂度的分析方法!!! 其实我觉得去b站找个动态的步骤分解视频也是不错的复习方法 ...

最新文章

  1. Java Web整合开发(85)
  2. SQLite 删除表
  3. 整理一下手头的几个域名
  4. thymeleaf公共页面元素抽取 || 引入片段的时候传入参数
  5. 详解Vue八大生命周期钩子函数
  6. Spring容器创建流程(2)创建beanFactory,加载BeanDefinition
  7. Android studio错误:module not specified
  8. 诺基亚接连巨亏:死守塞班难学摩托罗拉
  9. 使用USB直接方式解决ESXi识别加密狗的问题
  10. 打印机提示更换墨盒,但打印字仍很清晰,打印机设置还能用很久
  11. 机器学习之协方差矩阵、黑塞矩阵、标准差椭圆和EM算法
  12. html5网页构成要素有哪些,网页界面的构成要素
  13. python(turtle库)画七巧板
  14. 计算机鼠标能用键盘不能用,电脑键盘鼠标都不能用了,怎么回事?
  15. Namecheap无法登录
  16. 【Python军火库】Re基础入门:正则表达式
  17. 如何使用WooCommerce简码
  18. STM32F103C8T6基础开发教程(HAL库)—开发环境配置
  19. HTML实现图片360度循环旋转
  20. 正则表达式--常用用法及lookahead、lookbehind

热门文章

  1. jsp mysql事务锁,JSP操作数据库的事务回滚
  2. 【SQL】ROWNUM和ROWID
  3. 【Linux】计划任务管理crontab、at
  4. oracle Plsql 执行update或者delete时卡死问题解决办法
  5. php安装xmlwriter遇到报错及解决方法
  6. nginx+php-fpm页面显示空白的解决方法
  7. 如何在Android上使背景20%透明
  8. 如何从GET参数获取值?
  9. activiti删除已经部署的流程定义
  10. vue watch 修改滚动条_只需要这几个vue快捷开发技巧,看完技术提升30%!!!!...