递归
什么是递归
-
递归既是手段,又是计算思维方式
-
求解方法的递归性:方法是旧的,问题是新的
-
涉及的算法策略
-
蛮力法:是一种简单直接地解决问题的方法,常常直接基于问题的描述
-
分治法:把一个问题分成两个或无数多个相似的子问题,再把子问题分成更小的子问题,
直到可以直接求解,原问题的解即子问题解的合并
-
回溯法:一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”
-
动态规划法:运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果。
-
-
递归算法设计的框架
- 递归模型---->递归算法
- 求递归模型的步骤
- 对原问题f(s)进行分析,称为大问题,假设出合理的小问题f(s)’
- 假设f(s)‘是可解的,在此基础上确定f(s)的解,即给出f(s)与f(s’)之间的关系,即递归体
- 确定一个特殊情况如(f(1),f(0))的解,即递归出口
-
例求解最大数
int fmax(int a[],int i){ if (i==1){ return a[0]; }else{ return Math.max(fmax(a,i-1),a[i-1]); } }
递归算法设计
-
常见的递归数据
- 线性表
- 树
- 图
-
不带头结点的单链表的相关递归算法设计
- 为什么要不带头节点,因为带头的话,分割成无数个小问题时,小问题也要带头结点
- 对于空单链表的数据节点个数为0,f(L)=0,l=null
- 对于非空链表,f(L)=f(L–>next)+1
int count(LInkNOde *L){ if(L==NUll) return 0; else return count(L->next)+1; }
4.显示所有节点值
//正向显示 void traverse(LinkNode *L){ if(L==null) return ; printf("%d",L->data); traverSer(L->next); } //反向 void traverseR(LinkNode *L){ if(L==null) return; traverSer(L->next); printf("%d",L->data); }
-
假设二叉树采用二叉链表结构,设计一个递归算法由二叉树bt复制产生另一颗二叉树。
-
f(bt,bt1)=bt1=null
-
f(bt,bt1)=f(bt->1child,bt1->1child);f(bt->rchild,bt1->rchild)
-
void CopyBTree(BTNOde,*bt,BTNode *&bt1){ if(bt==null) bt1=null; else{ bt1=(BTNode *)malloc(sizeof(BTNode)); bt1->data=bt->data; CopyBTree(bt->lchild,bt1->lchild); CopyBtree(bt->rchild,bt1->rchild); } }
-
4. 用vector 向量path存放从根节点到x节点的正向路径
-
求解n的阶乘,0的个数
//求解原理:因式中5的个数 int ZEronum(int n){ if(n>0&&n<5) return 0; else{ int k=n/5; return k+Zeronum(k); } }
-
求解迷宫图
#include<studio.h> #define max_size=8 int h[4]={0,1,0,-1};//水平偏移量 int v[4]={-1,0,1,0};//垂直偏移量 char maze[max_size][max_size]={ {'x','x','x','x','x','x','x','x'}, {'0','0','0','0','x','x','x','x'}, {'x','x','x','0','x','x','x','x'}, {'x','x','x','0','x','x','x','x'}, {'x','x','x','0','x','x','x','x'}, {'x','x','x','0','0','0','x','x'}, {'x','x','x','x','x','0','x','x'}, {'x','x','x','x','x','0','0','0'} }; void FindPath(int x,int y){ //8*8迷宫 if(x==max_size-1&&y==max_size-1){ Maze[max_size-1][max_size-1]=''; for(int i=0;i<max_size;i++){ printf(" "); for(int j=0;j<max_size;j++) printf("%c",maze[i][j]); printf("\n"); } return; }else if(x>=0&&y>=0&&y<max_size &&x<max_size&&maze[x][y]=='0')//若(x,y)方块可走 { //试探每一个方位 for(int k=0;k<4;k++){ maze[x][y]=''; //将该方块设置为空字符 FindPath(x+v[k],y+H[k]);//查找(x,y)周围的每一个相邻方块 maze[x][y]='0';//找到路径,恢复(x,y) } } }
-
求解n皇后问题
#define N 20 int q[N]; int count=0; void dispasolution(int n){ printf("第%d个解:",++count); for(int i=1;i<=n;i++) printf("(%d,%d)",i,q[i]); printf("\n"); } //是否在同一条对角线上,|q[k]-j|==|i-k| //同一列 q[k]==j //同一行 k=x //冲突条件 (q[k]==j)||(abs(q[k]-j)==abs(i-k)) bool place(int i,int j){ if(i==1) return true; int k=1; while(k<i) { if((q[k]==j)||(abs(q[k]-j)==abs(i-k))) return fales; k++; } return true; } void queen(int i,int n){ if(i>n) dispasoulition(n); else{ for(int j=1;i<=n;j++) if(place(i,j)){ q[i]=j; queen(i+1,n); } } } void main(){ int n; queen(1,n);//放置1~n个皇后 }