数据结构-排序2

1.快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:

任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

1.1 hoare版本

左边选取key值,用一个keyi记录key值的位置,进入循环,右边先走,右边找小(不小就--),左边找大(不大就++),找到了就相互交换相对位置的数据,如果相遇就退出循环,然后交换相遇的位置和key值的位置,返回排序结束。

1.2挖坑法

基本思想和hoare版本的差不多,就是把key值位置的地方挖成一个坑,然后右边开始走,找小,把当前位置挖成一个新坑,把当前数据放到key值位置的坑位,之后左边开始走找大,找到就把数据放到右边的坑位,当前位置形成新的坑位,循环进行。

1.3前后指针法

基本思想:

用keyi记录key值,就是cur遍历,找到小的,prev就++并和cur位置的数据交换,然后cur++,如此循环反复,当cur>right的时候循环结束,交换prev和keyi的数据,上述代码改变的是prev++不等于cur的时候再交换,不用和自己交换,保持代码的健壮性和可观性。

1.4快排优化

避免有序的情况下,每次都会从右边一直遍历到最左边的key值,然后交换,左边没有数据,把右边整体再进行排序,使得效率退化。

1.4.1 三数取中法选key

将左区间,中间值和右区间作比较,取中间数当做key值换到最左边,然后进行排序。

1.4.2 小区间优化

递归到小的子区间时,因为快排本身需要继续进行左右子区间的递归,会降低效率和浪费内存利用率导致栈溢出,所以当递归到小区间时可以考虑使用插入排序,使得不再递归分割排序,减少递归的次数。

1.5快排的知识点

升序:

1.选取左边为key值,右边先走找小,左边找大,左右相遇的位置的数据一定是比key值小的。

2.选取右边为key值,左边先走找小,左边找大,左右相遇的位置的数据一定是比key值小的。

降序:

3.选取左边为key值,右边先走找大,左边找小,左右相遇的位置的数据一定是比key值大的。

4.选取右边为key值,左边先走找大,左边找小,左右相遇的位置的数据一定是比key值大的。

原因:以一为例

情况一:L遇到R,R停下是因为找到小了,L与R相遇位置的数据一定比key值小,然后交换。

情况二:R遇到L,R找小,没找到就会接着遍历,L的位置一定是上一次和R交换过的数据,二者相遇位置的数据一定是比key值小,然后交换。

1.6快排的非递归实现

这里我利用的是栈的后进先出的特性来实现的,函数调用建立栈帧,栈帧里面存储的核心就是函数的参数,这里就是数组的区间,这里就是不断的将右左区间的数值压栈,先入右区间,再入左区间,出栈顺序就是左区间和右区间了。

循环每走一次,取栈顶区间,单趟排序,右左子区间入栈。

1.7快速排序的特性总结

  1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序

  2. 时间复杂度:O(N*logN)

  3. 空间复杂度:O(logN)

  4. 稳定性:不稳定

2.归并排序

2.1基本思想:

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有 序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:

归并排序是需要新开个数组的,防止挪动数据导致覆盖数据。

通过选取中数划分两个左右区间,如果左右区间相等就直接返回,然后开始左右区间递归排序,分完子区间就开始归并,因为分完区间之后每个区间的数据都是有序的,如果左右子区间都没走完,两个左右子区间相比小的就拷贝尾插到新数组了,如果一边走完,就把另一边的数组拷贝尾插到新数组,左右子区间都走完循环就结束了,最后就使用memcpy将数据拷贝到目标数组里。

2.2归并排序的非递归实现

归并排序可以当做内排序也可以当做外排序,内排序是指在内存中操作,外排序是指数据量大而要在磁盘中操作。

2.3归并排序的特性总结

  1. 归并的缺点在于需要O(N)的空间复杂度,思考更多的是解决在磁盘中的外排序问题。

  2. 时间复杂度:O(N*logN)

  3. 空间复杂度:O(N)

  4. 稳定性:稳定

3.计数排序(非比较排序)

基本思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。

有上述代码可知,需要创建一个size为原数据个数的新数组来记录原数组每个数据出现的次数。

基本步骤:

1.统计每个数据出现的次数

2.排序-本质上是利用在count数组的自然序号排序,根据统计的结果将序列回收到原来的序列中

计数排序的特性总结:

  1. 计数排序在数据范围集中时,效率很高,但是适用范围及场景有限。

  2. 时间复杂度:O(MAX(N,范围))

  3. 空间复杂度:O(范围)

  4. 稳定性:稳定

4.基数排序(了解即可)

基本思想:按照整形的十进制位来进行排序,按照个位,十位,百位..的顺序来做比较。

5.桶排序(了解即可)

比较复杂且实用性不大,自己感兴趣可以搜索先关资料了解即可。

建立一个位node*的指针数组(size为10),十位相同的数据放在一个桶里排序。

适合比较均匀分布的2位数组。

6.排序算法复杂度及稳定性分析

相关推荐
重生之Java开发工程师1 分钟前
算法笔记:前缀和
笔记·算法
lin zaixi()4 分钟前
VSCode 下载 & 安装
ide·vscode·编辑器
m0_547486665 分钟前
数据结构试选择题及答案1
数据结构
知识鱼丸8 分钟前
【数据结构】一图介绍python数据结构
数据结构·python
sweetheart7-711 分钟前
LeetCode155. 最小栈(2024冬季每日一题 12)
算法··模拟栈·最小元素
藏鹤虞渊23 分钟前
【ONE·基础算法 || 动态规划(二)】
算法·动态规划
人才程序员25 分钟前
详解Qt QStorageInfo 存储信息类
c语言·开发语言·c++·后端·qt·界面
ZHOUPUYU27 分钟前
最新‌VSCode保姆级安装教程(附安装包)
c语言·开发语言·c++·ide·windows·vscode·编辑器
爱学嵌入式的菜鸟39 分钟前
Linux应用编程(C语言编译过程)
linux·c语言·ubuntu
kcwqxx1 小时前
day23|leetCode 39. 组合总和 , 40.组合总和II , 131.分割回文串
c++·算法·leetcode