- 浏览: 328993 次
- 性别:
- 来自: 西宁
-
文章分类
- 全部博客 (120)
- Java Thought (29)
- Java Pattern (4)
- Data Base (7)
- Algorithm Design (33)
- Linux (0)
- Mysql (2)
- Oracle (0)
- ConstructionDesign-架构 (5)
- Spring Platform (0)
- Tomcat (1)
- JavaScript (7)
- Web System (3)
- MS SQLServer (1)
- 软件哲学 (6)
- View (3)
- Java GUI (4)
- CSSDIV (7)
- CloudComputing (0)
- WebService (0)
- SystemOrProject (2)
- SOA (0)
- 互转共享 (3)
- 偶尔java习题 (0)
- Thinks with does (1)
最新评论
-
sassds:
佩服啊 高手
分享一款js特效 -
bhjackson:
学习啦,能否详细介绍下回溯的过程?O(∩_∩)O谢谢
分享回溯法- 找n个数中r个数的组合 -
zk7019311:
了解了解。。。。。
业务层代码复用的一点建议 -
lijie1819:
看到LZ的设计思想,感觉和抽象工厂模式有点相像。
业务层代码复用的一点建议 -
wjjcml1982:
酷毙了!楼主太强悍了!
分享一款js特效
1. 深入认识递归
(1) 递归执行过程
例子:求N!。
这是一个简单的"累乘"问题,用递归算法也能解决。
n! = n * (n - 1)! n > 1
0! = 1, 1! = 1 n = 0,1
因此,递归算法如下:
以n=3为例,看运行过程如下:
fact(3) ----- fact(2) ----- fact(1) ------ fact(2) -----fact(3)
------------------------------> ------------------------------>
递归 回溯
递归算法在运行中不断调用自身降低规模的过程,当规模降为1,即递归到fact(1)时,满足停止条件停止递归,开始回溯(返回调用算法)并计算,从fact(1)=1计算返回到fact(2);计算2*fact(1)=2返回到fact(3);计算3*fact(2)=6,结束递归。
算法的起始模块也是终止模块。
(2) 递归实现机制
每一次递归调用,都用一个特殊的数据结构"栈"记录当前算法的执行状态,特别地设置地址栈,用来记录当前算法的执行位置,以备回溯时正常返回。递归模块的形式参数是普通变量,每次递归调用得到的值都是不同的,他们也是由"栈"来存储。
(3) 递归调用的几种形式
一般递归调用有以下几种形式(其中a1、a2、b1、b2、k1、k2为常数)。
<1> 直接简单递归调用: f(n) {...a1 * f((n - k1) / b1); ...};
<2> 直接复杂递归调用: f(n) {...a1 * f((n - k1) / b1); a2 * f((n - k2) / b2); ...};
<3> 间接递归调用: f(n) {...a1 * f((n - k1) / b1); ...},
g(n) {...a2 * f((n - k2) / b2); ...}。
2. 递归算法效率分析方法
递归算法的分析方法比较多,最常用的便是迭代法。
迭代法的基本步骤是先将递归算法简化为对应的递归方程,然后通过反复迭代,将递归方程的右端变换成一个级数,最后求级数的和,再估计和的渐进阶。
<1> 例:n!
算法的递归方程为: T(n) = T(n - 1) + O(1);
迭代展开: T(n) = T(n - 1) + O(1)
= T(n - 2) + O(1) + O(1)
= T(n - 3) + O(1) + O(1) + O(1)
= ......
= O(1) + ... + O(1) + O(1) + O(1)
= n * O(1)
= O(n)
这个例子的时间复杂性是线性的。
<2> 例:如下递归方程:
T(n) = 2T(n/2) + 2, 且假设n=2的k次方。
T(n) = 2T(n/2) + 2
= 2(2T(n/2*2) + 2) + 2
= 4T(n/2*2) + 4 + 2
= 4(2T(n/2*2*2) + 2) + 4 + 2
= 2*2*2T(n/2*2*2) + 8 + 4 + 2
= ...
= 2的(k-1)次方 * T(n/2的(i-1)次方) + $(i:1~(k-1))2的i次方
= 2的(k-1)次方 + (2的k次方) - 2
= (3/2) * (2的k次方) - 2
= (3/2) * n - 2
= O(n)
这个例子的时间复杂性也是线性的。
<3> 例:如下递归方程:
T(n) = 2T(n/2) + O(n), 且假设n=2的k次方。
T(n) = 2T(n/2) + O(n)
= 2T(n/4) + 2O(n/2) + O(n)
= ...
= O(n) + O(n) + ... + O(n) + O(n) + O(n)
= k * O(n)
= O(k*n)
= O(nlog2n) //以2为底
一般地,当递归方程为T(n) = aT(n/c) + O(n), T(n)的解为:
O(n) (a<c && c>1)
O(nlog2n) (a=c && c>1) //以2为底
O(nlogca) (a>c && c>1) //n的(logca)次方,以c为底
上面介绍的3种递归调用形式,比较常用的是第一种情况,第二种形式也有时出现,而第三种形式(间接递归调用)使用的较少,且算法分析
比较复杂。 下面举个第二种形式的递归调用例子。
<4> 递归方程为:T(n) = T(n/3) + T(2n/3) + n
为了更好的理解,先画出递归过程相应的递归树:
n --------> n
n/3 2n/3 --------> n
n/9 2n/9 2n/9 4n/9 --------> n
...... ...... ...... ....... ......
--------
总共O(nlogn)
累计递归树各层的非递归项的值,每一层和都等于n,从根到叶的最长路径是:
n --> (2/3)n --> (4/9)n --> (12/27)n --> ... --> 1
设最长路径为k,则应该有:
(2/3)的k次方 * n = 1
得到 k = log(2/3)n // 以(2/3)为底
于是 T(n) <= (K + 1) * n = n (log(2/3)n + 1)
即 T(n) = O(nlogn)
由此例子表明,对于第二种递归形式调用,借助于递归树,用迭代法进行算法分析是简单易行的。
1. fact(int n) {
2. if(n == 0 || n == 1)
3. return 0;
4. else
5. return n * fact(n - 1);
6. }
return 0 ? 牛的。
仔细哦 已修正
1. fact(int n) {
2. if(n == 0 || n == 1)
3. return 0;
4. else
5. return n * fact(n - 1);
6. }
return 0 ? 牛的。
(1) 递归执行过程
例子:求N!。
这是一个简单的"累乘"问题,用递归算法也能解决。
n! = n * (n - 1)! n > 1
0! = 1, 1! = 1 n = 0,1
因此,递归算法如下:
fact(int n) { if(n == 0 || n == 1) return 1; else return n * fact(n - 1); }
以n=3为例,看运行过程如下:
fact(3) ----- fact(2) ----- fact(1) ------ fact(2) -----fact(3)
------------------------------> ------------------------------>
递归 回溯
递归算法在运行中不断调用自身降低规模的过程,当规模降为1,即递归到fact(1)时,满足停止条件停止递归,开始回溯(返回调用算法)并计算,从fact(1)=1计算返回到fact(2);计算2*fact(1)=2返回到fact(3);计算3*fact(2)=6,结束递归。
算法的起始模块也是终止模块。
(2) 递归实现机制
每一次递归调用,都用一个特殊的数据结构"栈"记录当前算法的执行状态,特别地设置地址栈,用来记录当前算法的执行位置,以备回溯时正常返回。递归模块的形式参数是普通变量,每次递归调用得到的值都是不同的,他们也是由"栈"来存储。
(3) 递归调用的几种形式
一般递归调用有以下几种形式(其中a1、a2、b1、b2、k1、k2为常数)。
<1> 直接简单递归调用: f(n) {...a1 * f((n - k1) / b1); ...};
<2> 直接复杂递归调用: f(n) {...a1 * f((n - k1) / b1); a2 * f((n - k2) / b2); ...};
<3> 间接递归调用: f(n) {...a1 * f((n - k1) / b1); ...},
g(n) {...a2 * f((n - k2) / b2); ...}。
2. 递归算法效率分析方法
递归算法的分析方法比较多,最常用的便是迭代法。
迭代法的基本步骤是先将递归算法简化为对应的递归方程,然后通过反复迭代,将递归方程的右端变换成一个级数,最后求级数的和,再估计和的渐进阶。
<1> 例:n!
算法的递归方程为: T(n) = T(n - 1) + O(1);
迭代展开: T(n) = T(n - 1) + O(1)
= T(n - 2) + O(1) + O(1)
= T(n - 3) + O(1) + O(1) + O(1)
= ......
= O(1) + ... + O(1) + O(1) + O(1)
= n * O(1)
= O(n)
这个例子的时间复杂性是线性的。
<2> 例:如下递归方程:
T(n) = 2T(n/2) + 2, 且假设n=2的k次方。
T(n) = 2T(n/2) + 2
= 2(2T(n/2*2) + 2) + 2
= 4T(n/2*2) + 4 + 2
= 4(2T(n/2*2*2) + 2) + 4 + 2
= 2*2*2T(n/2*2*2) + 8 + 4 + 2
= ...
= 2的(k-1)次方 * T(n/2的(i-1)次方) + $(i:1~(k-1))2的i次方
= 2的(k-1)次方 + (2的k次方) - 2
= (3/2) * (2的k次方) - 2
= (3/2) * n - 2
= O(n)
这个例子的时间复杂性也是线性的。
<3> 例:如下递归方程:
T(n) = 2T(n/2) + O(n), 且假设n=2的k次方。
T(n) = 2T(n/2) + O(n)
= 2T(n/4) + 2O(n/2) + O(n)
= ...
= O(n) + O(n) + ... + O(n) + O(n) + O(n)
= k * O(n)
= O(k*n)
= O(nlog2n) //以2为底
一般地,当递归方程为T(n) = aT(n/c) + O(n), T(n)的解为:
O(n) (a<c && c>1)
O(nlog2n) (a=c && c>1) //以2为底
O(nlogca) (a>c && c>1) //n的(logca)次方,以c为底
上面介绍的3种递归调用形式,比较常用的是第一种情况,第二种形式也有时出现,而第三种形式(间接递归调用)使用的较少,且算法分析
比较复杂。 下面举个第二种形式的递归调用例子。
<4> 递归方程为:T(n) = T(n/3) + T(2n/3) + n
为了更好的理解,先画出递归过程相应的递归树:
n --------> n
n/3 2n/3 --------> n
n/9 2n/9 2n/9 4n/9 --------> n
...... ...... ...... ....... ......
--------
总共O(nlogn)
累计递归树各层的非递归项的值,每一层和都等于n,从根到叶的最长路径是:
n --> (2/3)n --> (4/9)n --> (12/27)n --> ... --> 1
设最长路径为k,则应该有:
(2/3)的k次方 * n = 1
得到 k = log(2/3)n // 以(2/3)为底
于是 T(n) <= (K + 1) * n = n (log(2/3)n + 1)
即 T(n) = O(nlogn)
由此例子表明,对于第二种递归形式调用,借助于递归树,用迭代法进行算法分析是简单易行的。
评论
5 楼
dk101
2010-07-14
楼上“love_ai87 ”提到递归太深的话,容易导致JVM内存溢出,我也遇到过此问题,这个有什么好的解决办法吗?因为递归的深度(次数),大多数时候都是根据具体数据而定,所有就很头痛了。
4 楼
agao1985
2010-06-21
哎 递归好难啊 怎么学都学不会 太笨了我
3 楼
love_ai87
2010-06-21
递归次数太多的话,容易栈溢出
2 楼
maozj
2010-06-21
ivaneve 写道
引用
1. fact(int n) {
2. if(n == 0 || n == 1)
3. return 0;
4. else
5. return n * fact(n - 1);
6. }
return 0 ? 牛的。
仔细哦 已修正
1 楼
ivaneve
2010-06-21
引用
1. fact(int n) {
2. if(n == 0 || n == 1)
3. return 0;
4. else
5. return n * fact(n - 1);
6. }
return 0 ? 牛的。
发表评论
-
开散列的简单模拟(一)
2010-06-28 08:33 18521. 散列 散列有两种 ... -
递归和动态规划构造两个字符序列的最长公共字符子序列
2010-06-28 08:28 4519应je朋友要求,所以翻开以前的算法题目,整理了以下,给 ... -
最大公约数的应用 - 分享
2010-06-25 08:08 19001.先看一家大公司笔试题 数组中有n个数据,要将它们顺 ... -
信息数字化解逻辑题分享
2010-06-21 08:09 12821. 前提条件: 将逻辑题目中的信息用数字化描述。 ... -
非递归算法分析实例分享
2010-06-18 15:47 10741 仅仅依赖于问题规模的时间复杂度 (1) 例1: 交换i和 ... -
NP完全性问题
2010-06-18 14:02 7060在学习算法设计与分析时,经常会提到NP完全性问题,到底 ... -
算法分析精述分享
2010-06-18 12:03 9031. 算法分析的评价体系 评价算法的三条主要标准是: ... -
贪婪策略算法的总结分享
2010-06-11 08:30 61491. 贪婪算法描述 贪婪算法又叫登山法,它的根本思想是 ... -
带权有向图 - 边上权值非负情形的单源最短路径问题
2010-06-07 08:57 27191. 问题描述: 给定 ... -
是否很久没抽象和逻辑了呢? DODO它吧(很基础)四
2010-06-07 08:54 139621. 工作分配问题。 ... -
是否很久没抽象和逻辑了呢? DODO它吧(很基础)三
2010-06-07 08:53 113217. 字符统计问题。 编写一个算法,统计在一个输入 ... -
是否很久没抽象和逻辑了呢? DODO它吧(很基础)二
2010-06-07 08:47 14088. 数字迷问题。 A B C ... -
是否很久没抽象和逻辑了呢? DODO它吧(很基础)一
2010-06-07 08:38 12081. 线程问题。 设计4个线程,其中两个线程每次对j增加 ... -
是否很久没抽象和逻辑了呢? DODO它吧(很基础)
2010-06-07 08:37 19211. 线程问题。 设计 ... -
Java快速排序算法整理(二)
2010-05-31 14:04 1053package boke.sort; /** * 快 ... -
Java快速排序算法整理(一)
2010-05-31 13:39 677package boke.sort; /** * 快 ... -
Java最小堆实现
2010-05-31 08:29 59361.堆结点 package boke.heap1; /* ... -
Java插入排序代码整理
2010-05-28 14:44 1284package boke.sort; /** * 插 ... -
Java选择排序代码整理
2010-05-28 14:37 1542package boke.sort; /** * 选 ... -
Java冒泡排序代码整理
2010-05-28 14:26 2012Java冒泡排序代码整理: package boke.sor ...
相关推荐
本文实例讲述了C++使用递归和非递归算法实现的二叉树叶子节点个数计算方法。分享给大家供大家参考,具体如下: /*求二叉树叶子节点个数 -- 采用递归和非递归方法 经调试可运行源码及分析如下: ***/ #include #...
### 数据结构与算法分析C++描述习题答案 #### 一、引言 《数据结构与算法分析C++描述习题答案》这本书是基于Mark Allen Weiss教授的经典教材《数据结构与算法分析》编写的答案手册。Weiss教授的原著被誉为20世纪最...
通过分析源码,我们可以学习到如何在易语言环境中实现复杂的计算逻辑,这对于提升易语言编程技巧和理解递归算法都有很大帮助。同时,这样的资源也可以作为一个学习案例,帮助初学者更好地掌握递归的概念和应用。
1. **算法基础**:这部分主要介绍算法的基本概念,包括算法的定义、分类、设计原则以及分析方法。它会引导你理解算法在解决问题中的作用,如何评估算法的效率,以及常见的数据结构如数组、链表、栈、队列、树和图等...
- 在递归算法中,时间复杂度的分析通常涉及到递归树的概念,通过分析递归树的深度和每一层的操作数量来确定整体复杂度。 - 对于二分查找,每次都将问题规模减半,因此时间复杂度为O(log n)。 - 幂运算的递归实现...
在此次分享的案例中,就涉及到了将LSTM(长短期记忆网络)、TCN(时间卷积网络)以及多头注意力机制与传统的向量加权平均算法结合的尝试。 LSTM是一种特殊的RNN(递归神经网络)架构,它能够学习长期依赖信息。TCN...
#### 四、数据结构与算法分析 - **核心数据结构**: - 数组、链表、栈、队列、哈希表等基本数据结构的实现与应用。 - 树形结构(二叉树、平衡树等)的特点与应用场景。 - 图的相关概念及其在实际问题中的应用。 -...
在这一背景下,学者们提出了基于矮猫鼬优化算法DMOA-ESN(动态混合扩展递归神经网络)的北半球光伏数据预测模型,旨在提高光伏数据预测的准确性。 矮猫鼬优化算法(DMOA)是一种模拟自然界矮猫鼬觅食行为的优化算法...
变分模态分解(VMD)是一种有效的非递归信号处理技术,它能够将复杂的信号分解为有限数量的具有固有频率的子模态,这对于分析和提取光伏发电量数据中的有用信息至关重要。而海鸥优化算法(SOA)是一种模仿海鸥捕食...
本次分享的文件为一项未发表的创新研究,核心内容是利用龙格库塔优化算法和递归神经网络(RUN-ESN)来预测北半球的光伏数据。研究成果包含了完整的Matlab代码和案例数据,旨在为计算机科学、电子信息工程以及数学等...
本次分享的压缩包文件中包含了一套用负荷预测算法的Matlab实现,其核心是基于布谷鸟优化算法与CS-TCN-Attention模型的创新结合。这种算法的提出,对于电力系统负载预测领域具有显著的学术意义和应用价值。通过深入...
本次分享的《基于matlab遗传算法优化递归神经网络GA-ELMAN数据预测》是一份关于如何将遗传算法与Elman网络结合用于数据预测的详细指南。这份材料不仅包含了理论分析,还提供了具体的Matlab代码实现。通过阅读这份...
在本篇文档中,作者分享了一个基于链表实现的二叉树非递归遍历算法,具体实现了前序遍历。这种遍历方法不使用递归调用,而是通过循环和辅助栈来完成遍历过程,有助于节省内存资源并提高执行效率。 ### 二叉树的基本...
由于提供的文件信息中,【标题】与【描述】并没有提供具体的内容细节,仅提供了文件的标题和描述,以及一个百度网盘分享...它不仅覆盖了算法理论,还包含了大量的实例分析和习题,帮助读者通过实践来加深对算法的理解。
本实验的目的是让学生掌握递归算法设计和递归到非递归的转换方法,并了解单链表递归算法设计方法。 一、实验目的 通过本实验的学习,学生将领会基本递归算法设计和递归到非递归的转换方法,掌握单链表递归算法设计...
本次分享的是关于Matlab环境下实现的创新性白鲨优化算法WSO结合Kmeans聚类、Transformer模型和BiLSTM网络的组合状态识别算法研究。该研究针对状态识别这一课题,提出了一个新颖的算法组合框架,旨在提高识别的准确性...
递归算法是一种常见的编程技巧,它在解决一些特定问题时,比如汉诺塔问题、斐波那契数列计算等,可以发挥出色的作用。书中通过分析递归函数的执行过程和内存中的栈变化,阐释了递归过程中的递归调用和回溯机制。 ...
4. **递归与分治--快速排序算法**:快速排序是C.A.R. Hoare提出的一种高效排序算法,采用分治策略,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后分别对这两部分...
本次分享的是一项关于轴承故障分类的研究成果,该成果采用了名为“龙格库塔优化算法”的数学优化方法,并将其与“RUN-DBN”模型相结合,以实现对轴承故障的准确分类。龙格库塔方法是一种常用的常微分方程数值解法,...