程序=数据结构+算法
递归是一种应用非常广泛的算法。很多数据结构和算法的编码实现都要用到递归。
排序算法最经典最常用的冒泡插入选择,时间复杂度都为O()。
递归
递归需要满足的三个条件
- 一个问题的解可以分解为几个子问题的解
- 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
- 存在递归终止条件
分成递和归来看,我觉得和多重循环类似,就是一层套一层的,只不过是每一层都完成自己的工作,递给下一层就等待归。
也就是递推式+终止条件=递归算法
写递归代码的关键就是找到如何将大问题分解为小问题的规律,并且基于此写出递推公式,然后再推敲终止条件,最后将递推公式和终止条件翻译成代码。
递归堆栈溢出问题
函数调用会使用栈来保存临时变量,每调用一个函数,都会将临时变量封装为栈帧压入内存栈,等函数执行完成返回时,才出栈。
系统栈或者虚拟机栈空间一般都不大。如果递归求解的数据规模很大,调用层次很深,一直压入栈,就会有堆栈溢出的风险。
递归的重复计算
递归之中常会出现重复计算的问题,可以通过散列表哈希来解决问题。
排序算法(数组)
衡量一个排序算法
排序算法的执行效率
- 最好情况、最坏情况、平均情况时间复杂度
排序算法 | 最好情况 | 最坏情况 | 平均情况 |
---|---|---|---|
冒泡 | O(![]() | O(![]() | O(![]() |
插入 | O(![]() | O(![]() | O(![]() |
选择 | O(![]() | O(![]() | O(![]() |
- 时间复杂度的系数、常数 、低阶
实际的软件开发中,我们排序的可能是 10 个、100 个、1000 个这样规模很小的数据,所以,在对同一阶时间复杂度的排序算法性能对比的时候,我们就要把系数、常数、低阶也考虑进来
- 比较次数和交换(或移动)次数
基于比较的排序算法的执行过程,会涉及两种操作,一种是元素比较大小,另一种是元素交换或移动。
排序算法的内存消耗
原地排序将空间复杂度为O(1)的算法称为原地排序算法
排序算法的稳定性
经过某种排序算法排序之后,如果相同的元素排序前后顺序没有改变,那我们就把这种排序算法叫作稳定的排序算法;如果前后顺序发生变化,那对应的排序算法就叫作不稳定的排序算法。
冒泡排序
冒泡排序的具体过程还讲个锤子
- 原地排序
- 稳定的排序算法
- 时间复杂度(完全顺序,完全逆序)
插入排序
具体过程还讲个锤子
-
插入排序是原地排序算法
-
插入排序是稳定的排序算法
-
插入排序的时间复杂度是多少?
最好最坏时间复杂度(完全顺序,完全逆序)
选择排序
选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。
-
是原地排序算法
-
是不稳定的排序算法
-
时间复杂度是多少?
最好最坏时间复杂度(完全相同,因为每一个元素都需要对比)
排序算法(链表)
to be continued
2019年3月7日 19点59分