当前课程知识点:数据结构(上) > 第一章 绪论(下) > (e)迭代与递归 > 01-E-3: 递归跟踪
比如说
这就是一种可能的实现方法
我们看到 它是一个递归的形式
套用一下刚才的策略
对于n个数 求解这样一个问题
我们将它分解为一个
规模缩小了一个单元的问题
另外剩下的一个问题
本身是一个平凡的问题
可以直接求解得到
而我们要做的事情
只是递归地求解前者
并且将二者的解合并
在这里也就是做一个加法
而当这个问题的规模
一直缩小到足够小以后
本身也成为一个平凡的问题之后
就抵达了我们所说的递归基
这个时候 我们就直接地返回0
这个算法的正确性毋庸置疑
我们现在要回答的问题是
它的复杂度是多少呢?
是不是和刚才简单的
那种迭代的形式一样呢?
是比它高 还是比它要低?
我们下面介绍
递归式算法分析的
第一种主要技巧
也就是递归跟踪 recursion trace
具体来说 我们要把整个
递归调用的过程
用类似于这样的
一张图的形式表示出来
在这里 每一个递归实例
以及它们引发的递归实例
以及进而再引发的递归实例
都通过这样一个图的形式表示出来
每一个方块都对应于
一个递归实例
递归实例与递归实例之间
根据调用以及返回的次序
用箭头把它们连接起来
可以看到 就这个问题而言
整个的调用过程
或者说所有在这个计算过程中
曾经诞生过的递归实例
都可以按照线性的次序
排列成这样一个队列
我们看到 既然是减而治之
为了求解规模为n的问题
我们会生成一个
规模为n-1的问题
并且进而降解为n-2的问题
以及一直降解下去
直到最后变为规模为2 变为1
一直到规模退化到0
这个时候 才沿着相反的方向
逐步返回
我们说是的
这样一个图出来以后
我们就很清楚了
在整个这个计算过程中
所需要消耗的时间
应该就等于所有的递归实例
所需时间的累计总和
当然 这里有一条
就是我们每一个递归实例本身
还包含一个
调用由它所生成的那个
递归实例的语句
这个语句 在我们这里
以后 也要养成一个直觉习惯
凡是这种类似的语句
我们在分析复杂度的时候
都会直接把它抹掉
大家注意 这是抹掉
并不是真正地消失
而是把它忽略掉
因为这句本身的时间消耗是O(1)
而这个O(1)完全可以计入
由它生成的那个递归实例中去
这样的话 我们可以看得更加的清楚
那么 对于这个实例而言
总共有多少个递归实例?
各自又需要多少时间呢?
在我们经过了这样一个
消除之后看得很清楚
在这里 不仅没有了递归
而且 本身原来也不包含迭代循环
整个这个实例本身
所需要的时间
不论是它、它、它
还是以下各个递归实例
都应该是O(1)
所以对这个问题而言
它所需要的时间
应该就等于
所有的递归实例的总数
那么递归实例有多少呢?
这里看得很清楚
作为这样一个线性的次序下来的过程
自然地当然是有线性个
总体的当然就是渐近的O(n)
这样一种递归的形式
也是递归的最简单的形式
我们可以看到
每一个递归实例本身
只会生成至多一个递归实例
所有这些递归实例
按照这种关系
可以排成一个线性的次序
所以我们也管它叫作
linear recursion 线性递归
这也是最基本的一种形式
不难看出 递归跟踪
这种分析方法的应用范围
还是非常有限的
因为如果递归的形式
不是这样简单
而是相对复杂 甚至非常复杂
可能用再大的纸
用再多的时间
你有再大的耐心
你也不足以把所有的
这些递归实例都绘制出来
更不用说 再需要有
更强的概括能力
把其中的规律给概括出来
所以它的应用范围
我们说还是十分有限的
为了更好地分析
更为一般地更加复杂的
递归函数的复杂度
我们还需给出
更加强有力的一些其它的方法
比如说接下来要介绍的
递推分析的方法
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-OJ系统说明
--关于OJ
--1-注册与登录
--2-界面与选课
--3-提交测试
-关于课程教材与讲义
--课程教材与讲义
-关于讨论区
--关于讨论区
-微信平台
--html
-PA晋级申请
--PA晋级
-(a)计算
--演示
--(a)计算--作业
-(b)计算模型
-(b)计算模型--作业
-(c)大O记号
-(c)大O记号--作业
-(d)算法分析
-(d)算法分析--作业
-(e)迭代与递归
-(e)迭代与递归--作业
-(xc)动态规划
-- 演示
-(xc)动态规划--作业
-本章测验--作业
-(a)接口与实现
--02A-5 复制
-(a)接口与实现--作业
-(b)可扩充向量
-(b)可扩充向量--作业
-(c)无序向量
--02C-1 概述
--02C-3 插入
--02C-6 查找
--02C-8 遍历
-(c)无序向量--作业
-(d1)有序向量:唯一化
-(d1)有序向量:唯一化--作业
-(d2)有序向量:二分查找
-(d2)有序向量:二分查找--作业
-(d3)有序向量:Fibonacci查找
-(d3)有序向量:Fibonacci查找--作业
-(d4)有序向量:二分查找(改进)
-(d4)有序向量:二分查找(改进)--作业
-(d5)有序向量:插值查找
-第二章 向量(下)--(d5)有序向量:插值查找
-(e)起泡排序
--02E-2 改进
--02E-3 反例
-(e)起泡排序--作业
-(f)归并排序
-(f)归并排序--作业
-本章测验--作业
-(a)接口与实现
--03A-4 实现
-(a)接口与实现--作业
-(b)无序列表
--03B-2 查找
-(b)无序列表--作业
-(c)有序列表
--03C-3 查找
-(c)有序列表--作业
-(d)选择排序
--03D-1 构思
--03D-2 实例
--03D-3 实现
--03D-4 推敲
--03D-6 性能
-(d)选择排序--作业
-(e)插入排序
--03E-1 经验
--03E-2 构思
--03E-3 对比
--03E-4 实例
--03E-5 实现
-(e)插入排序--作业
-(xd)习题辅导:LightHouse
-本章测验--作业
- (a)栈接口与实现
--04A-1 栈
--04A-2 实例
--04A-3 实现
- (a)栈接口与实现--作业
-(c1)栈应用:进制转换
-第四章 栈与队列--(c1)栈应用:进制转换
-(c2)栈应用:括号匹配
-(c2)栈应用:括号匹配--作业
-(c3)栈应用:栈混洗
-第四章 栈与队列--(c3)栈应用:栈混洗
-(c4)栈应用:中缀表达式求值
-(c4)栈应用:中缀表达式求值--作业
-(c5)栈应用:逆波兰表达式
-第四章 栈与队列--(c5)栈应用:逆波兰表达式
-(d)队列接口与实现
--04D-1 接口
--04D-2 实例
--04D-3 实现
-第四章 栈与队列--本章测验
-(a)树
--05A-1 动机
--05A-2 应用
-(a)树--作业
-(b)树的表示
--05B-2 父亲
--05B-3 孩子
-第五章 二叉树--(b)树的表示
-(c)二叉树
-(c)二叉树--作业
-(d)二叉树实现
-(d)二叉树实现--作业
-(e1)先序遍历
-(e1)先序遍历--作业
-(e2)中序遍历
-第五章 二叉树--(e2)中序遍历
-(e4)层次遍历
-第五章 二叉树--(e4)层次遍历
-(e5)重构
-(e5)重构--作业
-本章测验--作业
-(a)概述
-(a)概述--作业
-(b1)邻接矩阵
-(b1)邻接矩阵--作业
-(c)广度优先搜索
--06C-2 策略
--06C-3 实现
--06C-5 实例
-(c)广度优先搜索--作业
-(d)深度优先搜索
--06D-1 算法
--06D-2 框架
--06D-3 细节
-(d)深度优先搜索--作业
-第六章 图--本章测验