欢迎Star,本文的所有示例源码都在Github:
本篇内容包含
- 排序的介绍
- 排序的C的实现
- 排序的Java的实现
- 排序的时间复杂度的计算
1、基本思想:
两个数比较大小,较大的数下沉,较小的数冒起来
2、实现步骤:
这张图就是将数字12,35,99,18,76竖起来
- 第一次:从底部有一个气泡,圈住12并且和35对比,如果比上面小就交换,气泡往上升
- 第二次:12和99对比,如果比上面小就交换,气泡往上升
- 第三次:重复上面的操作,最后可以把12排到最上面
3、这张图模拟了冒泡排序的整个过程
- 第一个红色框表示气泡
- 两个红色框表示比较大小
- 黑色框表示已经排好的数字
- 最后排成有序的数字
1、程序优化:
- 这里加了一个flag作为优化程序的条件,如果程序未进入内循环,说明数字已经排序好了,后面的比较也就没有意义了,直接程序结束
2、实现口诀:
- 两数相抱转个圈
3、易犯错误:
- 忘记添加优化flag
1、我们从代码分析,可以知道有两个循环
- 外循环:执行(n-1)次,当最坏的情况下,会执行n次,虽然最后一次(i < n)不通过,但还是算一次,其中里面有一条赋值语句
- 内循环:在(i=1,2,3…n-1),执行(n-i)次,即(n-1,n-2…1),其中有四条赋值语句
2、那么就可以计算出各自复杂度
- 外循环:最坏情况下是(1 x n)次
- 内循环:通过等差数列求和公式,(n-1+n-2+…1)=n^2/2
3、根据推导大O阶规则来进行推导
- 用常数1来取代运行时间中所有加法常数
- 修改后的运行次数函数中,只保留最高阶项
- 如果最高阶项存在且不是1,则去除与这个项相乘的常数
4、得到的冒泡排序的复杂度的大O表示法为
(1xn)+(n^2/2) ≈ n^2=O(n^2)
1、基本思想:
- 让第一个数与后面的所有数一个个比较,找出最小的数,将最小的数跟第一个数交换
- 接着从第二个数开始,继续上面的操作
2、实现步骤:
1、注意点:
- 用语言实现排序的时候,只是记录着最小值的下标,接着用最小值的下标继续和后面的数进行比较,这是和思路不同的地方
2、实现口诀:
- 角标互换
3、易犯错误:
- 忘记添加角标判断
1、我们从代码分析,可以知道有两个循环
- 外循环:执行(n-1)次,当最坏的情况下,会执行n次,虽然最后一次(i < n)不通过,但还是算一次,其中里面有四条赋值语句
- 内循环:在(j=1,2,3…n-1),执行(n-i)次,即(n-1,n-2…1),其中有一条赋值语句
2、那么就可以计算出各自复杂度
- 外循环:最坏情况下是(4 x n)次
- 内循环:通过等差数列求和公式,(n-1+n-2+…1)=n^2/2
3、复杂度的大O表示法为
(4xn)+(1x(n^2/2)) ≈ n^2=O(n^2)
1、基本思想:
- 其实就是你玩扑克牌的时候,排序你自己的牌的思路
- 从后面抽出牌,插入到前面的牌中
2、实现步骤:
- 初始值:1, 4, 8, 3, 2, 9, 5, 0, 7, 6
- 第一次:抽出牌4,与1对比,发现比它大,不交换
- 第二次:抽出牌8,与4对比,发现比它大,不交换
- 第三次:抽出牌3,与8对比,发现比它小,交换,继续与前面一个数比,与4对比,发现比它小,交换,继续与前面一个数比,与1对比,发现比它大,不交换
- 第四次:重复上面步骤,完成扑克牌排序
1、实现口诀:
- 扑克牌往回插
2、易犯错误:
- 忘记退出的break
1、我们从代码分析,可以知道有两个循环
- 外循环:执行(n-1)次,当最坏的情况下,会执行n次,虽然最后一次(i < n)不通过,但还是算一次
- 内循环:在(i=0,1,2,3…n-2),执行(n-i-1)次,即(n-1,n-2…1),其中有三条赋值语句
2、那么就可以计算出各自复杂度
- 外循环:最坏情况下是(n)次
- 内循环:通过等差数列求和公式,3x(n-1+n-2+…1)=(3x(n^2/2))
3、复杂度的大O表示法为
(n)+(3x(n^2/2)) ≈ n^2=O(n^2)
1、基本思想:
- 先对所有的数进行分组
- 对分组的数进行插入排序
2、实现步骤:
这张图就是将数字9,1,2,5,7,4,8,6,3,5,按分量(数的个数/2)进行分组,然后在各分组中进行插入排序
- 第一次:按分量5分成5组,在组中分别进行插入排序
- 第二次:按分量2分成5组,在组中分别进行插入排序
- 第三次:按分量1分成5组,在组中分别进行插入排序
1、实现口诀:
- 分组,插入
2、易犯错误:
- 忘记添加结束break
1、基本思想:
- 整理小顶堆
- 将小顶堆a[0]和a[i]和互换
- 将换下来后的a[i]取出,即最大数
- 继续整理小顶堆
1、基本思想:
- 以第一个数(a)为基准
- 分别在头部和尾部添加指针
- 右边指针先开始,遇到比a小的数则停止
- 左边指针后开始,遇到比a大的数则停止
- 交换右边和左边的指针数
- 重复上述步骤,直到两指针相等
- 交换a与两指针指向的数
1、基本思想:
- 先将需要排序的数,按中点进行分组
- 重复分组,直到分到的组不能再分
- 比较最后分开的两个组
- 哪个组的数小,就取谁,取了后就在对应数列中删除这个数
- 重复取数,直到两组的数被完全取出,合并取出来的所有数
- 重复上述比较、取数、合并的步骤,最后合并成有序数组
在学习基数排序之前,必须要知道桶排序,所以先简单的学习一下桶排序
1、基本思想:
- 首先创建数组A[MaxValue]
- 将每个数放到相应的位置上,即数的值和索引相等的位置
- 最后遍历数组,即为排序后的结果
1、基本思想:
- 将每个数的个位开始进行桶排序
- 排序完成后,桶按顺序输出
- 将排序好个位的数,进行十位开始桶排序
- 排序完成后,桶按顺序输出
- 重复上述步骤,直到最高位进行桶排序,按顺序输出即为结果
排序类型 | 时间复杂度 |
---|---|
冒泡排序 | O(n^2) |
选择排序 | O(n^2) |
插入排序 | O(n^2) |
希尔排序 | O(n^1.5) |
堆排序 | O(N*logN) |
快速排序 | O(N*logN) |
归并排序 | O(N*logN) |
基数排序 | O(d(n+r)) |