递归算法的一些实例
来源:互联网 发布:单片机学习 编辑:程序博客网 时间:2024/06/08 10:11
递归算法的一些实例
递归算法实际上只需要找出递归表达式,或者说是n与n-1之间的关系即可,由于是直接调用自身,所以使用递归解决问题的函数通常都是很短的,因为只需要描述n与n-1之间的关系,以及终止递归的条件。
(1)阶乘
比如一个最简单的递归例子,求n的阶乘,递归的过程就是n*(n-1),终止的条件就是n=1,所以这个子函数就可以写成:
unsigned fac(unsigned n){ unsigned f; if (n==0) f = 1; else f = fac(n-1)*n; return f;}
(2)排列组合
并非只有存在数学表达式的例子才能用递归的思想,只要能找出n和n-1的关系即可,比如说求n个人里面选k个人的组合数,已知如下关系:
由n选k个的组合数 = 由n-1选k个的组合数 + 由n-1选k-1的组合数
那么递归的表达式就可以写成:
f(n,k) = f(n-1,k) + f(n-1.k-1);
子函数可以写成:
int comm(int n,int k){ if(n < k) return 0; else if(n == k || k == 0) return 1; else return comm(n-1,k) + comm(n-1,k-1);}
(3)汉诺塔
再比如经典的汉诺塔(Hanoi)问题
古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个和尚想把这64个盘子从A座移到C座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。在移动过程中可以利用B座,要求打印移动的步骤。如果只有一个盘子,则不需要利用B座,直接将盘子从A移动到C。
这样想这个问题:
如果有2个盘子,可以先将盘子1上的盘子2移动到B;将盘子1移动到c;将盘子2移动到c。这说明了:可以借助B将2个盘子从A移动到C,当然,也可以借助C将2个盘子从A移动到B。
如果有3个盘子,那么根据2个盘子的结论,可以借助c将盘子1上的两个盘子从A移动到B;将盘子1从A移动到C,A变成空座;借助A座,将B上的两个盘子移动到C。这说明:可以借助一个空座,将3个盘子从一个座移动到另一个。
如果有4个盘子,那么首先借助空座C,将盘子1上的三个盘子从A移动到B;将盘子1移动到C,A变成空座;借助空座A,将B座上的三个盘子移动到C。
从上面的过程来看,将n个盘子从A移动到C需要以下三个步骤:
1,将n-1个盘子移动到B;
2,将A上剩余的一个盘子移动到C;
3,将B上n-1个盘子移动到C。
上述步骤中,1和3都是将n-1个盘子从一个座移动到另一个座,这是递归过程,因为n-1个盘子的移动也需要上述三个步骤。。。以此类推,我们可写出实现汉诺塔问题的子函数:
void move(char A,char C){ cout<<A<<"-->"<<C<<endl;}void hanoi(int n,char A,char B,char C){ if (n==1) move(A,C); else hanoi(n-1,A,C,B); move(A,C); hanoi(n-1,B,A,C);}
注意hanoi子函数中形参的顺序,因此第一个步骤是把n-1个盘子以C为中介从A移动B,而第三个步骤是把n-1个盘子以A为中介从B移到C。
(4)二叉树
二叉树是一种非常常见的数据结构,二叉树定义为每个结点最多有两个子树的树结构,左边的树称为“左子树”,右边的树称为“右子树”。
二叉树的建立是一个很明显的递归过程,因为一个结点生出两个树,这两个树的结点又分别对应生出两颗树……
二叉树的建立过程如下:
首先要建立一个二叉树的结点类:
class BitNode{ public: ...//略 private; char data; BitNode *leftchild; BitNode *rightchild; }
public里面的成员函数先不用管,主要是完成一些初始化,左右树的设置和读取的工作。需要注意的是在私有成员里定了了用于存储数据的data,以及以及左右两个指针。
建立一个二叉树类:
class BiTree{ public: ... BiTree* create_tree();//创建二叉树 void pre_order(BitNode *r);//前序遍历 void in_order(BitNode *r);//中序遍历 void post_order(BitNode *r);//后序遍历 private: BitNode *root;}
创建二叉树:
BitNode* BiTree::create_tree(){ BitNode* T; char item; cin>>item; if (item != '#') { T = new BitNode; T->data = item; T->leftchild = create_tree(); T->rightchild = create_tree(); return T; } else { T = NULL; return T; }}
前中后序遍历分递归方法和非递归方法,此处只举递归的方法:
void BiTree::pre_order(BitNode *T){ if (T != NULL) { cout<<T->data; pre_order(T->leftchild); pre_order(T->rightchild); }}void BiTree::in_order(BitNode *T){ if(T != NULL) { in_order(T->leftchild); cout<<T->data; in_order(T->rightchild); }}void BiTree::post_order(BitNode *T){ if (T != NULL) { post_order(T->leftchild); post_order(T->rightchild); cout<<T->data; }}
- 递归算法的一些实例
- 一些递归算法的实现
- PHP递归算法的简单实例
- 一些基本算法的递归实现
- 一些基本算法的递归实现
- 递归算法经典实例
- 递归算法实例讲解
- 递归算法实例
- 递归算法实例讲解
- Java递归算法实例
- 递归算法实例
- 递归算法实例讲解
- 递归算法实例讲解
- 算法的一些小栗子6(递归算法)
- JAVA递归算法实例小结
- JAVA递归算法实例小结
- php递归算法经典实例
- 一个经典的递归算法题(实例+源码)
- Gulp+webpack模板化开发演练(1):分离公共头文件
- java.lang.SecurityException: Permission Denial:错误解决办法
- UVA 1331 Minimax Triangulation [最优三角剖分] [dp] [计算几何]
- 使用pthreads基本函数编写helloworld.c
- java--css(2)选择器
- 递归算法的一些实例
- @Autowired学习笔记
- Maven安装
- 如何指定tomcat下的某个项目的具体文件为网站的首页面
- 介绍 Android DropBoxManager Service
- Object-Oriented Analysis and Design Using UML 翻译与学习 (三)
- C++的inline
- IOC的前世今生
- Android自定义ViewGroup(一)之CustomGridLayout