zoukankan      html  css  js  c++  java
  • 第1章 C++回顾

    1.7 递归函数

    练习 19 - 26

      1 #include <iostream>
      2 #include <cmath> // pow(double base, double exp) 
      3 #include <ctime>
      4 using namespace std;
      5 
      6 // 《数据结构,算法与应用》中递归的相应题目
      7 // 第一章17-26
      8 // P28 ~ P30
      9 
     10 // 19. n! 
     11 int calculate_factorial_of_n_with_non_recursive_program(int n)
     12 {
     13     // 0 的阶乘是 1 
     14     if (n == 0)
     15         return 1;
     16     // 负数没有阶乘 
     17     else if (n < 0)
     18     {
     19         throw "Negative numbers have no factorials!";
     20         return -1;
     21     }    
     22     else
     23     {
     24         int factorial_result = 1;
     25         // n! = n x (n-1) x (n-2) x ... x 1 
     26         while(n > 1)
     27         {
     28             factorial_result *= n;
     29             n -= 1;
     30         }
     31         return factorial_result;
     32     }    
     33 }
     34 
     35 int calculate_factorial_of_n_with_recursive_program(int n)
     36 {
     37 // f(n) = { 1, if n = 1
     38 //            n * f(n-1), else
     39 //          }
     40     // 0 的阶乘是 1 
     41     if (n == 0)
     42         return 1;
     43     // 基础部分 
     44     else if (n == 1)
     45         return 1;
     46     // 负数没有阶乘
     47     else if (n < 0)
     48     {
     49         throw "Negative numbers have no factorials!";
     50         return -1;
     51     }
     52     // 递归部分
     53     // n! = n x (n-1) x (n-2) x ... x 1 
     54     else
     55         return n * calculate_factorial_of_n_with_recursive_program(n-1);
     56 }
     57 
     58 // 测试19 
     59 void test_calculate_factorial()
     60 {
     61     int n = 0;
     62     try
     63     {
     64         int result = calculate_factorial_of_n_with_non_recursive_program(n);
     65         cout << "With non-recursive program, factorial of n = ";
     66         cout << result;
     67     }
     68     // 捕获 n 为负数的异常    
     69     catch(const char* e)
     70     {
     71         cout << e;
     72     }    
     73     cout << endl;
     74     
     75     try
     76     {
     77         int result = calculate_factorial_of_n_with_recursive_program(n);
     78         cout << "With recursive program, factorial of n = ";
     79         cout << result;
     80     }
     81     catch(const char* e)
     82     {
     83         cout << e;
     84     }    
     85     cout << endl;
     86 }
     87 
     88 // ============================================================================================================================================= //
     89 
     90 // 20. 斐波那契数列(Fibonacci sequence) 
     91 int calculate_Fibonacci_with_recursive_funcation(int n)
     92 {
     93     if (n == 0)
     94         return 0;
     95     else if (n == 1)
     96         return 1;
     97     else 
     98         return calculate_Fibonacci_with_recursive_funcation(n-1) + calculate_Fibonacci_with_recursive_funcation(n-2);
     99 } 
    100 
    101 int calculate_Fibonacci_with_non_recursive_funcation(int n)
    102 { 
    103     int* a = new int[n+1];
    104     a[0] = 0; a[1] = 1;
    105     for (int i = 2; i <= n; i ++)
    106         a[i] = a[i-1] + a[i-2];
    107     return a[n];
    108 }
    109 
    110 // 测试20
    111 void test_calculate_Fibonacci()
    112 {
    113     int n = 7;
    114     cout << "With recursive funcation, Fibonacci sequence F(" << n << ") = ";  
    115     cout << calculate_Fibonacci_with_recursive_funcation(n);
    116     cout << endl;
    117     
    118     cout << "With non-recursive funcation, Fibonacci sequence F(" << n << ") = ";  
    119     cout << calculate_Fibonacci_with_non_recursive_funcation(n);
    120     cout << endl;
    121 }
    122 
    123 
    124 // ============================================================================================================================================= //
    125 
    126 // 21.
    127 int calculate_f_n_with_recursive_funcation(int n)
    128 {
    129     if(n % 2 == 0)// 偶数 
    130         return n / 2;
    131     else
    132         return calculate_f_n_with_recursive_funcation(3*n+1);    
    133 }
    134 
    135 int  calculate_f_n_with_non_recursive_funcation(int n)
    136 {
    137     if (n % 2 == 0)// 偶数
    138         return n / 2;
    139     else// 奇数,则 3n+1 定为偶数 
    140         return  (3 * n + 1) / 2;
    141 }
    142 
    143 // 测试21
    144 void test_f_n()
    145 {
    146     int n = 4;
    147     cout << "With recursive funcation, f(" << n << ") = ";  
    148     cout << calculate_f_n_with_recursive_funcation(n);
    149     cout << endl;
    150     
    151     cout << "With non-recursive funcation, f(" << n << ") = ";  
    152     cout << calculate_f_n_with_non_recursive_funcation(n);
    153     cout << endl;
    154 } 
    155  
    156 // ============================================================================================================================================= //
    157 
    158 // 22. 阿克曼函数
    159 int calculate_Ackermann_funcation(int i, int j)
    160 {
    161     if (i < 1 || j < 1)
    162         return -1;
    163     if (i == 1 && j >= 1)
    164         return pow(2.0, j);    
    165     else if (i >= 2 && j == 1)
    166         return calculate_Ackermann_funcation(i-1, 2);
    167     else
    168         return calculate_Ackermann_funcation(i-1, calculate_Ackermann_funcation(i, j-1));
    169 }
    170 
    171 // 测试22
    172 void test_Ackermann_funcation()
    173 {
    174     int i = 2, j = 2;
    175     cout << "Ackermann`s funcation("  << i << ", " << j << ") = ";
    176     cout << calculate_Ackermann_funcation(i, j);
    177     cout << endl;
    178 } 
    179 
    180 // ============================================================================================================================================= //
    181 
    182 // 23. 最大公约数(Greatest Common Divisor,GCD) 
    183 int calculate_GCD_with_recursive_funcation(int x, int y)
    184 {
    185     if (y == 0)
    186         return x;
    187     else
    188         return calculate_GCD_with_recursive_funcation(y, x%y);        
    189 }
    190 
    191 int calculate_GCD_with_non_recursive_funcation(int x, int y)
    192 {
    193     if (x < y) // 保证 x > y 
    194         swap(x, y);
    195     
    196     while(y != 0)
    197     {
    198         int temp = x % y;
    199         x = y;
    200         y = temp;
    201     }
    202     return x; 
    203 }
    204 
    205 // 测试23 
    206 void test_GCD()
    207 {
    208     int x = 18, y = 24;
    209     cout << "With recursive funcation, GCD(" << x << ", " << y << ") = ";  
    210     cout << calculate_GCD_with_recursive_funcation(x, y);
    211     cout << endl;
    212     
    213     cout << "With non-recursive funcation, GCD(" << x << ", " << y << ") = ";
    214     cout << calculate_GCD_with_non_recursive_funcation(x, y);
    215     cout << endl;
    216 }
    217 
    218 // ============================================================================================================================================= //
    219 
    220 // 24.
    221 template<class T>
    222 int search_for_x_in_array_a(const T a[], const T x, int start, int end)
    223 {
    224     if (start > end)
    225         return -1;
    226     else
    227     {
    228         int middle = int((start + end) / 2);
    229         if(a[middle] == x)
    230             return middle; 
    231         // cout << middle << endl;
    232         else 
    233         {
    234             int index = search_for_x_in_array_a(a, x, start, middle-1);
    235             // cout << endl << middle << endl;
    236             if (index == -1) // 关键 
    237                 search_for_x_in_array_a(a, x, middle+1, end);
    238         }
    239     }
    240 }
    241 
    242 // 测试24
    243 void test_search_x()
    244 {
    245     int a[] = {5, 2, 45, 7, 8, 3};
    246     int a_x = 2;
    247     //int a_x = 10;
    248      
    249     char b[] = {'a', 'c', 'w', 'p', 'r', 'o'};
    250     char b_x = 'w';
    251     //char b_x = 'e';
    252     cout << a_x << "在数组a中的下标为:"; 
    253     cout << search_for_x_in_array_a(a, a_x, 0, 6-1);
    254     cout << endl;
    255     cout << b_x << "在数组b中的下标为:"; 
    256     cout << search_for_x_in_array_a(b, b_x, 0, 6-1);
    257     cout << endl;
    258 }
    259 
    260 // ============================================================================================================================================= //
    261 
    262 // 25. 子集生成方法
    263 int sequence[10000][10000];
    264 int subset_generation(int n)
    265 {
    266     if (n == 0)
    267     {// 空集的子集只有空集 
    268         cout << 0 << endl;
    269         return 1;
    270     } 
    271     else if (n == 1)
    272     {
    273         for (int i = 0; i <= 1; i ++)
    274             sequence[i][1] = i; 
    275         return 2;
    276     }
    277     else
    278     {
    279         int row_length = subset_generation(n-1);
    280         int cur_row_length = 2 * row_length; 
    281         // 拷贝两遍 n-1 个元素的信息 
    282         for (int row = row_length; row < cur_row_length; row ++)
    283             for (int col = 1; col <= n-1; col ++)
    284                     sequence[row][col] = sequence[row-row_length][col];
    285         // 添加第 n 个元素
    286         for (int row = 0; row < cur_row_length; row ++)
    287             sequence[row][n] = row < row_length? 0 : 1;        
    288         return cur_row_length;
    289     }    
    290 }
    291 
    292 
    293 void subset_generation_with_non_recursive_funcation(const int n)
    294 {// 转二进制 
    295     int subset[n] = {0};
    296     // n 位二进制转其能表示的最大十进制
    297     int number = 1;
    298     for (int i = n-1; i > 0; i --) 
    299         number += pow(2.0, i);
    300     
    301     for (int i = 0; i <= number; i ++)
    302     {
    303         int temp_n = n;
    304         int temp_i = i;
    305         while(temp_i > 0)
    306         {
    307             subset[temp_n-1] = temp_i % 2;
    308             temp_i /= 2;
    309             temp_n --;
    310         }
    311         for(int j = 0; j < n; j ++)
    312             cout << subset[j];
    313         cout << endl;
    314     }
    315      
    316 }
    317  
    318 // 测试25 
    319 void test_subset_generation()
    320 {
    321     // n must lower than seven
    322     // int n = 10;
    323     int n = 3;
    324     time_t start_time = time(0); 
    325     // cout << start_time << endl;
    326     cout << "all subsets are:" << endl;
    327     int length = subset_generation(n);
    328     if (length <= 1)
    329         return;
    330     for (int i = 0; i < length; i ++)
    331     {
    332         for (int j = 1; j <= n; j ++)
    333             cout << sequence[i][j];
    334         cout << endl;
    335     }
    336     time_t end_time = time(0);
    337     cout << end_time - start_time << endl;
    338     start_time = time(0);
    339     cout << "with non-recursive_way, all subsets are:" << endl;
    340     subset_generation_with_non_recursive_funcation(n);
    341     end_time = time(0);
    342     cout << end_time - start_time << endl;
    343     // 经测试,递归快一点 
    344     
    345 }
    346  
    347  
    348 // ============================================================================================================================================= //
    349 
    350 // 26.格雷码(Gray Code)
    351 void print_Gray_code_of_n(int n)
    352 {
    353     if (n == 1)
    354         cout << 1 << ' ';
    355     else
    356     {
    357         print_Gray_code_of_n(n-1);
    358         cout << n << ' ';
    359         print_Gray_code_of_n(n-1);    
    360     }    
    361 } 
    362 
    363 // 测试26
    364 void test_gray_code()
    365 {
    366     int n = 3;
    367     cout << "Gray Code is:"; 
    368     print_Gray_code_of_n(n);
    369 } 
    370  
    371 
    372 // ============================================================================================================================================= //
    373 int main()
    374 {
    375     // 测试19 
    376     test_calculate_factorial();
    377     
    378     // 测试20 
    379     test_calculate_Fibonacci();
    380     
    381     // 测试21
    382     test_f_n(); 
    383     
    384     // 测试22
    385     test_Ackermann_funcation();
    386     
    387     // cout << 18 % 24<< endl;
    388     // 18
    389     // 测试23 
    390     test_GCD();
    391     
    392     // 测试24
    393     test_search_x();
    394     
    395     // 测试25 
    396     test_subset_generation();
    397     
    398     // 测试26
    399     test_gray_code(); 
    400     return 0;
    401 }
    402  

     24. 编写一个递归模板函数,确定元素x是否属于数组a[0: n-1]。

      我编写的是一个查找无须数组的递归版折半查找法(尽管折半查找不支持无序?)

      search函数在a中查找x的步骤如下图所示

      遇到的问题:

      一开始没有第236行(黄色标记行),导致查找结果一直为-1。

      原因:

      查找结束时,递归函数返回上一层,不会中断(跳出所有的递归层)。又因为没有225行的if语句判断,故当前层的递归函数向下继续运行。

      解决办法:

      在236行加上if判断

      代码见

     25. [子集生成方法(Subset Generation)]编写一个C++递归函数,输出n个元素的所有子集。例如,三元素集{a,b,c}的子集是{}(空集),{a},{b},{c},{a,b},{a,c},{b,c},{a,b,c}。这些子集用0/1组成的代码序列来表示分别是000,100,010,001,110,101,011,111(0表示相应的元素不在子集中,1表示相应的元素在子集中)。因此你的程序输出长度为n的0/1序列即可。

      子集生成法的实质:n位二进制的种数。

      (1)递归法

        当 n = 0 时,即该  n 元素集为空集, 空集的子集只有一个空集,故输出为 0。

        当 n = 1 时,即 1 元素集,比如{ a },它有两个子集{ }, { a }, 故输出为 0、1。

        当 n = 2 时,即 2 元素集,比如{ a,  b },它有四个子集{ }, { a },{ b },{ a,b},故输出为 00、10、 01、 11。

        ............

        下面我们用表格来表示一下规率。

    
    
    表1:n = 1
    0
    1

       如何由表 1 推到表 2:
        第一步:将表 1 拷贝两遍,形成表 2 的蓝色区域
        第二步:将第二个元素的两种取值(0,1)插入表 2, 如表 2 绿区域所示。

      
    表2:n = 2
    0 0
    1 0
    0 1
    1 1
       表 2 推表 3 的步骤与表 1 推表 2 的步骤相同。
    表3:n = 3
    0 0 0
    1 0 0
    0 1 0
    1 1 0

    0 0 1
    1 0 1
    0 1 1
    1 1 1

        上述的表 1 到 表 3 是即为程序中的sequence,它采用二维表格存储结果。

        代码见

      (2)二进制法

        代码见



    全部代码见

      https://github.com/Hu-Xiaoming/Data-Structures/blob/master/recursive%20code/practiceOfRecursion_19-26.cpp

  • 相关阅读:
    three.js中 用 鼠标点击+呼吸灯
    socket.io学习以及在vuehtml使用,node搭建的后台
    网路在线古诗文免费阅读网站
    vue-element-admin默认加载Dashboard更改
    vue-element-admin后台框架侧边蓝图标添加自定义
    吸顶操作vue
    对图片进行裁剪(vueCropper)图片不显示
    ucharts使用内容
    文字转换为语音在线免费工具连接
    tree.js外部骨骼动画
  • 原文地址:https://www.cnblogs.com/uhanhi/p/13061597.html
Copyright © 2011-2022 走看看