递归

来源:互联网 发布:武汉国企java招聘信息 编辑:程序博客网 时间:2024/06/14 16:44

栈的应用:递归
将函数的调用位置,局部变量和寄存器等信息作为1种称作激活记录的数据结构。(图P147和P148)
用通用方法将大型问题简化为类似性质但规模更小的问题。
一直递归直到将子问题简化到无需递归即可解答。

  • 关键步骤:确定普遍使用的划分原则
  • 停止规则:确定算法能够处理特例,例如什么不做时能正常返回。
  • 递归函数执行关键步骤直到符合停止规则

将指令放在一个区域,将其他数据放在每个用户独立的区域

注意尾部递归:当函数最后执行的语句(不一定是程序的最后一句)是递归调用。可以通过while/do while循环改为迭代减少空间复杂度。

通过递归树来判断使用迭代还是递归:

  1. 当递归树不存在重复任务(例如斐波那契数列P150)且树很茂密,考虑使用迭代;
  2. 树的形式简单考虑迭代。
  3. 迭代(自底向上,由已知到未知)和栈能代替递归,递归(自顶向下,从未知分解为已知)能替代栈。

范例:

  1. 分而治之
  2. 树结构
  3. 回溯:

    • 构造部分解,当与问题需求不一致时,移去最近构造的解并倒退,尝试另一种可能。
    • 适合随着不断的测试能减少可能的数量

八皇后问题(皇后可以横/竖/对角线)
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的玩家失败。
由于在合理的运行时间内无法探查所有的分支,只能通过评价函数返回利益的估计值。

原创粉丝点击