快速排序--QuickSort()--递归版本
一、快速排序(递归版本)
1.快速排序模板(初始版本)
void QuickSort(int* a, int begin, int end)
{// 区间不存在,或者只有一个值则不需要在处理if (begin >= end){return;}int keyi = PartSort1(a, begin, end);// [begin, keyi-1] keyi [keyi+1, end]QuickSort(a, begin, keyi - 1);QuickSort(a, keyi+1, end);
}
存在问题、特点:
1.递归次数过多
2.有序等的极端情况会使其递归过深,导致栈溢出
3.没优化前,快排的效率和key的选取有关,选越靠近最大,或者越靠近最小的数,效率越慢;越靠近中位数,效率越快。
2.快速排序模板(优化版本)
void QuickSort(int* a, int begin, int end)
{//callCount++;//printf("%p\n", &callCount);// 区间不存在,或者只有一个值则不需要在处理if (begin >= end){return;}if (end - begin > 10){int keyi = PartSort1(a, begin, end);// [begin, keyi-1] keyi [keyi+1, end]QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);}else{InsertSort(a+begin, end - begin + 1);//当区间过小时,可以直接用插入排序,较为高效}
}
图示:
优点:
假设总共有n个元素需要排的话,递归层次越深,所需要排序的次数也就越多,例:第一次要排两次,第二次要排四次,...,最后一次要2^h次,---(.h从0开始,树有h-1层,则树的总节点数为 n=2^(h+1) -1.得h=log(n+1) -1)---能看得出最后一次就占了全部排序次数的50%。 所以该优化方法,可以大大的减少排序的次数和递归的次数。
3.快速排序的三个方法partsort()
(1)hoare版本 时间复杂度:O(N*logN)
int PartSort1(int* a, int begin, int end)
{int left = begin, right = end;int keyi = left;while (left < right){// 右边先走,找小while (left < right && a[right] >= a[keyi]){--right;}// 左边再走,找大while (left < right && a[left] <= a[keyi]){++left;}Swap(&a[left], &a[right]);}Swap(&a[keyi], &a[left]);keyi = left;return keyi;
}
(2)挖洞法
int PartSort2(int* a, int begin, int end)
{int key = a[begin];int piti = begin;while (begin < end){// 右边找小,填到左边的坑里面去。这个位置形成新的坑while (begin < end && a[end] >= key){--end;}a[piti] = a[end];piti = end;// 左边找大,填到右边的坑里面去。这个位置形成新的坑while (begin < end && a[begin] <= key){++begin;}a[piti] = a[begin];piti = begin;}a[piti] = key;return piti;
}
(3)前后指针法 (进一步优化了模板--加入了getmid三数取中原则--减少了对有序序列排序时递归过深等的极端情况)
int GetMidIndex(int* a, int begin, int end)
{int mid = (begin + end) / 2;if (a[begin] < a[mid]){if (a[mid] < a[end]){return mid;}else if (a[begin] < a[end]){return end;}else{return begin;}}else if(a[begin] >= a[mid]){if (a[mid] > a[end]){return mid;}else if (a[begin] < a[end]){return begin;}else{return end;}}
}int PartSort3(int* a, int begin, int end)
{int prev = begin;int cur = begin + 1;int keyi = begin;// 加入三数取中的优化--用于随机选midi放到keyi,使keyi既不是最大也不是最小int midi = GetMidIndex(a, begin, end);Swap(&a[keyi], &a[midi]);while (cur <= end){// cur位置的之小于keyi位置值if (a[cur] < a[keyi] && ++prev != cur)Swap(&a[prev], &a[cur]);++cur;}Swap(&a[prev], &a[keyi]);keyi = prev;return keyi;
}
4.疑惑解答
(1)hoare法 和 挖洞法 为什么 左边做key 一定要右边先走?
答:
1.R先走,R停下来,L去遇到R
可以保证:相遇位置就是R停下的位置,R的位置是比key要小的,确保后续和key交换时,是小的交换去左边了,大的在右边.
2.R先走,若R没有找到比key要小的值,R直接去到L
可以保证:相遇位置是L上一轮停下来的位置(要么就是key,要么就是比key要小的值。)
也确保了用R遇到的交换到左边的是key或者比key大的值.L交换到右边的是key或者比key要小的值
结论:左边做key,右边先走;右边做key,左边先走。
快速排序--QuickSort()--递归版本相关推荐
- 快速排序 递归版本和非递归方法 c代码
快速排序平均时间是T(n) =knln(n),其中n为待排序序列中记录个数,k为某个常数.通常,快速排序被认为是,在所有同数量级(O(nlogn))的排序方法中,其平均性能最好,但是,若初始记录按关键 ...
- 排序下---(冒泡排序,快速排序,快速排序优化,快速排序非递归,归并排序,计数排序)
排序上 排序上 交换类排序 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. ...
- 分治法 —— 快速排序(递归,迭代,非递归)
快速排序 快速排序三种方法,你值得参考!!! 快速排序 1,快速排序之递归 Code 递归 2,快速排序之迭代 Code 迭代 3,快速排序之非递归 Code 非递归 4,结语 快速排序在所有排序中基 ...
- 快速排序(quickSort) 和 插入排序(insertSort)
1.快速排序(quickSort) (1)在数据集之中,选择一个元素作为"基准"(pivot). (2)所有小于"基准"的元素,都移到"基准" ...
- quicksort java_Java代码实现快速排序(QuickSort)
Java代码实现快速排序(QuickSort) 核心思想 如果要排序数组中下标从p到r之间的一组数据,我们选择p到r之间的任意一个数据为pivot(分区点). 我们遍历p到r之间的数据,将小于pivo ...
- 快速排序(Quick-Sort)及优化
文章目录 前置基础知识 随机算法与快速排序 再来看快速排序 从C++STL 学习快速排序 算法题实战 排序数组 排序链表 盛水最多的容器 最小K个数 剑指offer21 调整数组顺序使奇数位偶数前面 ...
- 二叉树的中序遍历(递归和非递归版本)
难易程度:★★ 重要性:★★★★★ 树结构是面试中的考察的重点,而树的遍历又是树结构的基础.中序遍历的非递归版本要求重点理解掌握. /*** 非递归版本的中序遍历* node指向待处理的节点,在中序遍 ...
- 快速排序(quicksort)算法实现
快速排序(quicksort)是分治法的典型例子,它的主要思想是将一个待排序的数组以数组的某一个元素X为轴,使这个轴的左侧元素都比X大,而右侧元素都比X小(从大到小排序).然后以这个X在变换后数组的 ...
- 2021-10-7 !二叉树的前序、中序、后序遍历 (递归版本)
非常重要,等下次复习补一张系统栈的图 //前序遍历,递归版本,三个遍历的递归写法思想都一致,唯一区别就是在什么时候访问根结点 //画个图和栈更好理解,这里不多解释 void BinarySearchT ...
最新文章
- 在CentOS 7.7 x86_64上安装python3的selenium 3模块实录
- 「九章」量子计算优越性遭北大院士质疑,潘建伟陆朝阳长文回应
- Android开发--详解ContentProvider/Cursor的使用
- 洛谷P2280 [HNOI2003]激光炸弹
- “请先做自我介绍”:高手都是这样做自我介绍,这样介绍最加分
- 三国杀服务器改名 插图修改,《三国杀》大幅修改的武将——新旧两版,你更喜欢哪一位...
- linux文件控制驱动程序,Linux设备驱动程序学习(6)-高级字符驱动程序操作[(3)设备文件的访问控制]...
- java九九成表发_用EXCEL可多种办法生成99乘法表
- Keras及其前端配置
- adb shell am 的用法
- Java基于JSP+Servlet的校友论坛管理系统
- Adding a Timepicker to jQuery UI Datepicker
- 嵌入式Linux设备驱动程序开发指南17(IIO子系统一)——读书笔记
- 利用动态二进制加密实现新型一句话木马之Java篇(转) 冰蝎
- CAD中遇到几个奇怪问题的解决
- python智力问答游戏代码,python实现智力问答测试小程序
- C语言结构体详解(结构体定义,使用,结构体大小等)
- html倒计时10s,vue做30s倒计时,在最后10s倒数的时候有个放大的效果
- Scrapy爬取北京公交并保存MYSQL数据库实例
- 慧荣SM2259XT主控贴镁光B27A测试分享
热门文章
- 移动端使用fiddler抓包步骤
- 使用python封装了一个获取小程序token,发送订阅消息的类
- 中心差分法编程C语言,中心差分法的基本理论与程序设计.docx
- PPT中插入高亮代码——PPT对象
- python len ljust_python中ljust的用法
- 在数据库中如何新增一个字段?
- Arduino连接LCD1602显示屏
- HTML5期末大作业:宠物之家网站设计——代码质量好宠之家(5页) HTML+CSS+JavaScript web期末作业设计网页
- linux下usb充电问题,如何解决在Ubuntu上iPad不能充电的问题
- 主属性,范式,超码,码,非主属性,全码