1 / 74

栈与递归 递归与回溯 广义表

第五章 递归. 栈与递归 递归与回溯 广义表. 一、栈和递归. 递归定义 递归函数. 递归定义. 先定义最基本的概念 再用已定义的概念定义新的概念. 例 命题演算公式的定义 ( 1 ) 单个命题变元符号是命题 ( 2 ) 如果 A,B 是命题,则 (┐A), (A∧B), (A∨B), (A→B), ( A←→B) 都是公式. 递归定义. 先定义最基本的概念 再用已定义的概念定义新的概念. 例 标识符的定义

ivory
Télécharger la présentation

栈与递归 递归与回溯 广义表

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第五章 递归 • 栈与递归 • 递归与回溯 • 广义表

  2. 一、栈和递归 • 递归定义 • 递归函数

  3. 递归定义 • 先定义最基本的概念 再用已定义的概念定义新的概念 例 命题演算公式的定义 (1) 单个命题变元符号是命题 (2) 如果A,B是命题,则 (┐A), (A∧B), (A∨B), (A→B), (A←→B) 都是公式

  4. 递归定义 • 先定义最基本的概念 再用已定义的概念定义新的概念 例 标识符的定义 (1)单个英文字母是标识符 (2)标识符后缀一个数字 或一个英文字母是标识符

  5. 递归函数的定义 • 一个算法可以分解成 若干相同的小算法 分解到某简单的子算法时终止 • 有一个或几个终止条件 递归:由其前面的值求当前值 递归必须导致终止条件

  6. 递归函数的例 例 函数 xn x0=1 xn=x*xn-1n>0 xn=xn-1/x n<0 例 函数 n! 0!=1 n!=n*(n-1)!n>0

  7. 递归函数的例 函数 C(n, m) C(0, m)=1, C(m, m)=1. C(n, m)=C(n-1,m-1)+C(n, m-1)

  8. #include <iostream.h> // compute n! = n*(n-1)*(n-2)...(2)(1), 0!=1 recursively long Factorial(long n) { // if n == 0, then 0! = 1; otherwise, n! = n*(n-1)! if (n == 0) return 1; else return n * Factorial(n - 1); }

  9. void main (void) { int i, n; // enter 4 positive integers and compute n! for each cout << "Enter 4 positive integers: "; for (i = 0; i < 4; i++) { cin >> n; cout << n << "! = " << Factorial(n) << endl; } }

  10. /* <Run > Enter 4 positive integers: 0 7 1 4 0! = 1 7! = 5040 1! = 1 4! = 24 */

  11. 阶乘堆栈

  12. 递归函数 先操作 后遍历 例 void Fucnc(char ch) { if(ch<=‘z’) { cout<<ch; Func(ch+1); } } 调用 Func(‘a’); 输出 abcdefghijklmnopqrstuvwxyz

  13. 递归函数 先遍历 后操作 例 void Fucnc(char ch) { if(ch<=‘z’) { Func(ch+1); cout<<ch;} } 调用 Func(‘a’); 输出 zyxwvutsrqponmlkjihgfedcba

  14. 递归函数 操作 遍历 操作 例 void Fucnc(char ch) { if(ch<=‘z’) { cout<<ch; Func(ch+1); cout<<ch;} } 调用 Func(‘a’); 输出 abcdefghijklmnopqrstuvwxyz zyxwvutsrqponmlkjihgfedcba

  15. 递归函数 遍历 操作 遍历 例 void Fucnc(char ch) { if(ch<=‘d’) { Func(ch+1); cout<<ch; Func(ch+1); } } 调用 Func(‘a’); 输出 dcdbdcdadcdbdcd

  16. 河内塔问题

  17. 河内塔问题将A塔上的金盘移到B塔上 !要求 一次只能移动一个盘 大盘不能压小盘

  18. 河内塔问题 第一次

  19. 河内塔问题 第二次

  20. 河内塔问题 第三次

  21. 河内塔问题 第四次

  22. 河内塔问题 第五次

  23. 河内塔问题 第六次

  24. 河内塔问题 第七次

  25. 河内塔问题 设n个金盘移动 F(n)次 F(1)=1 F(n)=F(n-1)+1+F(n-1)=2*F(n-1)+1 F(n)+1=2*(F(n-1)+1) =22*(F(n-2)+1) =······ =2n-1*(F(1)+1)=2n F(n)=2n-1

  26. 河内塔问题程序 #include <iostream.h> #pragma hdrstop #include "strclass.h" // move n disks from startpeg to endpeg, // using middlepeg as the intermediate peg

  27. void hanoi(int n, char A, char B, char C) { if (n == 1) cout << “move ”<<A << " → " < B << endl; else { hanoi(n-1,A, C, B); cout << “move ”<<A << " → " << B << endl; hanoi(n-1, C, B, A); } }

  28. void main( ) { int n; // number of disks and the peg names cout << "Enter the number of disks: "; cin >> n; cout << "The solution for n = " << n << endl; hanoi(n, ‘A’, ‘B’, ‘C’); }

  29. /* <Run 河内塔问题> Enter the number of disks: 3 The solution for n = 3 move A → B move A → C move B → C move A → B move C → A move C → B move B → C */

  30. 迷宫maze struct Intersection {int left; int forword; int right; }; 回溯 此路不通,返回 回溯 此路不通,返回 回溯 此路不通,返回 回溯 此路不通,返回 6 0 2 0 3 5 6 0 0 4 0 0 0 0 0 0 7 0 0 7

  31. 二、递归和回溯 • 迷宫算法 • 八皇后问题

  32. // record that specifies the intersection you // arrive at when departing left, forward or right // from the current intersection struct Intersection { int left; int forward; int right; };

  33. #include <iostream.h> #include <fstream.h> #include <stdlib.h> class Maze { int mazesize; int EXIT; Intersection *intsec; public: Maze(char *filename); int TraverseMaze(int intsecvalue); };

  34. Maze::Maze(char *filename) { ifstream fin; int i; fin.open(filename, ios::in | ios::nocreate); if (!fin) { cerr << "The maze data file " << filename << " cannot be opened!" << endl; exit(1); } fin >> mazesize; intsec = new Intersection[mazesize+1]; for (i = 1; i <= mazesize; i++) fin >> intsec[i].left >> intsec[i].forward >> intsec[i].right; fin >> EXIT; fin.close( ); }

  35. 回溯法 一个变量控制递归 用另一个变量来控制回溯 出现特定情况时该变量取值0 回溯 1。全局变量 2。变量参数 引用变量,指针变量 3。函数返回值

  36. int Maze::TraverseMaze(int intsecvalue) { if (intsecvalue > 0) {if (intsecvalue = = EXIT) { cout << intsecvalue << " "; return 1; } else if (TraverseMaze(intsec[intsecvalue].left)) { cout << intsecvalue << " "; return 1; } else if (TraverseMaze(intsec[intsecvalue].forward)) {cout << intsecvalue << " "; return 1; } else if (TraverseMaze(intsec[intsecvalue].right)) { cout << intsecvalue << " "; return 1; } } return 0; }

  37. #include <iostream.h> #pragma hdrstop #include "maze.h" // include the maze class

  38. void main (void) { char filename[32]; cout << "Enter the data file name: "; cin >> filename; Maze M(filename); if (M.TraverseMaze(1)) cout << "\nYou are free!" << endl; else cout << "No path out of the maze" << endl; }

  39. //maze1.dat 6 0 2 0 3 5 6 0 0 4 0 0 0 0 0 0 7 0 0 7

  40. //maze2.dat 11 0 2 0 3 0 5 0 0 4 0 0 0 6 7 0 0 0 0 8 0 0 9 0 0 0 11 10 0 0 0 0 0 0 12

  41. //bigmaze.dat 18 0 2 0 3 8 0 7 4 0 0 6 5 0 0 0 0 0 0 0 0 0 9 0 0 0 0 10 14 0 11 12 13 0 0 0 0 0 0 0 0 15 16 0 0 0 17 0 0 0 18 19 0 0 0 19

  42. /* <Run #1 > Enter the data file name: maze1.dat 7 6 2 1 You are free! <Run #2 > Enter the data file name: maze2.dat No path out of the maze <Run #3 > Enter the data file name: bigmaze.dat 19 17 16 14 10 9 8 2 1 You are free. */

  43. 迷宫的另一种模型

  44. 迷宫的另一种模型

  45. 八皇后问题 要求:一个棋盘上摆八个皇后,任意两个都不互相杀死 两皇后在同一行或同一列 或同一对角线上互相杀死

  46. 皇后的表示 • 用二维数组表示8*8棋盘 皇后用棋盘上的格点表示 • 用坐标表示皇后的位置 (a, 4) (1, 4) • 用一维数组表示皇后的位置 int q[9]; q[1]=4; 表示第一行第四列有一个皇后 q[4]=2; 表示第四行第二列有一个皇后

  47. 两个皇后冲突的特征 (a1, b1)与 (a2, b2)冲突 当且仅当 a1= b1或a2= b2或 | a1- b1|=| a2- b2| q[i]与q[j]冲突 当且仅当 i= j或 q[i]=q[j]或 | i - j |=| q[i] - q[j] |

  48. 三、广义表 LS=(a1, a2,······,an) 长度 n 每个 ai1≤i≤n 或是一个元素(原子), 或是一个子广义表。 a1是表头head, a2,······,an是表尾。 用小写字母表示原子,大写字母表示广义表。

  49. 广义表的例 A=( ) 长度为0的空表。 B=(e) 只有一个元素的表,长为1。 C=(a,(b,c,d)) 长度为2的广义表,第二个 元素是长度为3的子表。 D=(A,B,C) 长度为3的广义表,三个 元素都是长度为3的子表。 D=(( ),(e),(a,(b,c,d))) E=(a,E) 递归定义的表。 E=(a,(a,(a,······))).

  50. 广义表的存储 广义表的结点

More Related