递归
来源:互联网 发布:武汉国企java招聘信息 编辑:程序博客网 时间:2024/06/14 16:44
栈的应用:递归
将函数的调用位置,局部变量和寄存器等信息作为1种称作激活记录的数据结构。(图P147和P148)
用通用方法将大型问题简化为类似性质但规模更小的问题。
一直递归直到将子问题简化到无需递归即可解答。
- 关键步骤:确定普遍使用的划分原则
- 停止规则:确定算法能够处理特例,例如什么不做时能正常返回。
- 递归函数执行关键步骤直到符合停止规则
将指令放在一个区域,将其他数据放在每个用户独立的区域
注意尾部递归:当函数最后执行的语句(不一定是程序的最后一句)是递归调用。可以通过while/do while循环改为迭代减少空间复杂度。
通过递归树来判断使用迭代还是递归:
- 当递归树不存在重复任务(例如斐波那契数列P150)且树很茂密,考虑使用迭代;
- 树的形式简单考虑迭代。
- 迭代(自底向上,由已知到未知)和栈能代替递归,递归(自顶向下,从未知分解为已知)能替代栈。
范例:
- 分而治之
- 树结构
回溯:
- 构造部分解,当与问题需求不一致时,移去最近构造的解并倒退,尝试另一种可能。
- 适合随着不断的测试能减少可能的数量
八皇后问题(皇后可以横/竖/对角线)
solve_form函数:从给定的皇后位置递归查找解答
Queens configuration:已选择的路径
configuration:棋盘上所有的位置
solve_form(Queens configuration)检查Queens configuration是否违背规则,违背直接返回if已有八个 打印结束else for_each configuration未选择的位置{ 选择下一个皇后在configuration的位置 solve_form(Queens configuration); 移除 }
int main(){ int board_size;//放置的皇后数量 cin>>board_size; if(board_size<0 || board_size>max_board ) cout<<"…"<<endl; else{ Queens_configuration(board_size); solve_form(configuration); }}
//根据第count行第col列的格子是否能够放置bool Queens::unguarded(int col)const;
//没违反则插入,count+1bool Queens::insert(int col);
//已摆放的数量是否等于board_sizebool Queens::is_sovled()const;
solve_form(Queens_configuration){ if( configuration.is_solved() ) configuration.print(); else for(int col=0;col<configuration.board_size; ++col) if( configuration.unguarded(col) ){ configuration.insert(col); solve_form(configuration); configuration.remove(col); } }
const int max_board=0;class Queens{public: Queens(int size); bool is_solved()const; void print()const; //判断是否可以放置 bool unguarded(int col)const; void insert(int col); void remove(int col); int board_size;private: int count; bool queen_square[max_board][max_board];};
Queens::Queens(int size){ board_size=size; count=0; for(int row=0;row<board_size;++row) for(int col=0;col<board_size;++col) queen_square[row][col]=false;}
void Queens::insert(int col){ queen_square[count-1][col]=true;}
bool Queens::unguarded(int col)const{ int i; bool ok=true; for(i=0; ok&&i<count ;++i) ok= !queen_square[i][col]; for(i=0; ok&&count-i>=0&&col+i<board_size ;++i) ok= !queen_square[i][col]; return ok;}
优化
- 建议1:将所有不能放置的数组同时标记
- 建议2:使用3个数组记录可以使用的格子
class Queens{…private: int count; bool col_free[max_board]; bool upward_free[max_board]; bool downward_free[max_board]; int queen_in_row[max_board];};
bool Queens::unguarded(int col)const{ return col_free[col] && upward_free[count+col]; && downward_free[count+col+board_size-1];}
游戏树:
2个玩家轮流选择123中的一个数字,并且不能选择上一轮的数字。2个玩家所选的数字之和等于8时的玩家获胜;使和大于8的玩家失败。
由于在合理的运行时间内无法探查所有的分支,只能通过评价函数返回利益的估计值。