• 数据结构 递归笔记


    /*
    递归:
    简单的说就是函数自己调用自己常用来解决一些复杂的问题。
    采用递归的算法的特征:
        为求解规模为N的问题,可以将其分解为较小规模的问题,并且这些问题
        还可以划分为规模更小的问题。从而从这些规模小的问题求解出原问题。
        一般,问题规模为 1 时的解是已知的,即递归的出口。
    递归的优点:
        使用递归使程序简洁,结构清晰,可读性强。
    递归的缺点:
        效率较低,运行时开销较大。
        
    说明:
        由于递归形式的定义容易使人们使用递归来解决问题,但递归并不一定
        适合这个问题,例如:使用递归计算斐波拉契数列时,由于递归的实现
        是通过函数调用,而每一个递归调用都会触发另外的递归调用,以此类
        推,需要的计算量增加的非常快,会造成大量不必要的浪费。而使用循
        环来代替递归计算斐波拉契数列,虽然循环形式不如递归形式符合斐波
        拉契数列的抽象定义,但循环的效率却比递归提高了很多。 
    */
    // 利用递归的思想求解斐波拉契序列
     
    # include <stdio.h>
    
    int Fic(int);
    
    int main(void)
    {
        int n, aim;
        printf("请输入您想要求解的数所在的位置:");
        scanf("%d", &n); 
        aim = Fic(n);
        printf("
    aim = %d
    ", aim);
        
        return 0;
     } 
     
     int Fic(int n)
     {
         if (n < 3)
         {
             return 1;
        }
        else
        {
            return Fic(n-1)+Fic(n-2);
        }
     }
    /*
    编写一个递归函数,要求给定一个正整数 n ,输出所有和为 n 的
    所有不增的正整数和式。
    例如:
    当 n = 3 时 
    3 = 3
    3 = 2 + 1
    3 = 1 + 1 + 1 
    */
    
    # include <stdio.h>
    # include <stdlib.h>
    # include <malloc.h>
    
    void Add_Type(int * arry, int i, int k);   // 输出所有不增和式 
    
    int main(void)
    {
        int n;
        printf("Data: ");
        scanf("%d", &n);
        printf("Result: 
    ");
        // 构造一个保存和式中所有项的数组,数组长度最长为 n+1
        int * arry = (int *)malloc(sizeof(int) * (n+1));
        if (NULL == arry)
        {
            printf("动态内存分配失败!
    ");
            exit(-1);
        }
        arry[0] = n;  // 数组第一个保存和式的和 
        Add_Type(arry, n, 1);
        
        return 0;
    } 
    
    void Add_Type(int * arry, int i, int k)  // k 表示和式新的一项开始出现的位置 
    {
        int j, p;
        for (j = i; j >= 1; --j)  // 使和式呈从n开始依次递减的形式出现 
        {
            if (j <= arry[k-1])   // 保证和式不出现项的数目与值不变,只是出现次序发生改变的情况
            {
                arry[k] = j;  // 此时使数组中下标为 k 的元素储存了和式此时的最后一项 
                if (j == i)
                {
                    printf("%d = %d", arry[0], arry[1]);
                    for (p = 2; p <= k; ++p)   // 打印和式的剩余项 
                    {
                        printf(" + %d", arry[p]);
                    }
                    printf("
    "); 
                }
                Add_Type(arry, i-j, k+1);  // 即将 i-j 继续拆分为不增和式的剩余项 
            } 
        }
        
        return;
    }
    /*
         经典算法——1 汉诺塔: 有三个柱子和 n 个大小各不相同的
         盘子。开始时,所有盘子以塔状叠放在柱子 A 上,要求一定规
         则,将柱子 A 上的所有盘子移到柱子 B 上,柱子 C 为移动缓
         冲柱。
         移动规则如下:
            (1)一次只能移动一个盘子。
            (2)任何时候不能把盘子放在比他小的盘子下面。
    */

    /*
        采用递归的方法解决此问题。
        (1)描述解决问题的思想:
               1. 若只有一个盘子,则可以直接从A移动到B
               2. 若盘子数大于 1 ,则需要先将 n-1 个盘子从 A 移动
               到缓冲区 C ,再将 A 中剩下的最大的一个盘子移动到终
               点盘 B ,最后再将缓冲区 C 上的 n-1 个盘子移动到终
               点盘 B 。
        (2)递归算法(见下面代码)
    */

    # include
    <stdio.h> void hanoi(int, char, char, char); int main(void) { int disks; // 定义盘子总数。 printf("请输入盘子总数目:"); scanf("%d", &disks); printf(" "); hanoi(disks, 'A', 'B', 'C'); // A 为最开始盘子所在的地方 B 为最后盘子要放置的地方 C 为缓冲地带 return 0; } void hanoi(int n, char A, char B, char C) // A 为最开始盘子所在的地方 B 为最后盘子要放置的地方 C 为缓冲地带 { if (1 == n) { printf("%c 移到 %c", A, B); } else // 整个移动过程中的一个基本单元 { // hanoi 函数中的不同的盘子作用要与形参一致, 见下一个改变了盘子功能的程序 hanoi(n-1, A, C, B); // 将 n-1 个盘子从起始区移到缓冲区 printf(" "); printf("%c 移到 %c", A, B); // 将最大的盘子移到终点区 printf(" "); hanoi(n-1, C, B, A); // 将缓冲区的 n-1 个盘子移到终点区 printf(" "); } return; } /* 输出结果: 请输入盘子总数目:4 A 移到 C A 移到 B C 移到 B A 移到 C B 移到 A B 移到 C A 移到 C A 移到 B C 移到 B C 移到 A B 移到 A C 移到 B A 移到 C A 移到 B C 移到 B -------------------------------- Process exited after 1.463 seconds with return value 0 请按任意键继续. . . */

     注意:

    递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但
    循环的逻辑不如递归清晰。
    使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实
    现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于
    栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。 

  • 相关阅读:
    WEB测试方法(二)
    WEB测试方法(一)
    JSP技术(六)
    JSP技术(七)
    JSP技术(四)
    JSP技术(三)
    JSP技术(五)
    JavaScript语言和jQuery技术(四)
    单元测试的四个阶段
    什么是集成测试
  • 原文地址:https://www.cnblogs.com/lnlin/p/6771204.html
Copyright © 2020-2023  润新知