数据结构 - 递归

来源:互联网 发布:起名字软件 编辑:程序博客网 时间:2024/06/10 00:12
郝斌版《数据结构》学习笔记
时间:2015.08.31 - 2015.09.05


函数调用前系统准备三件事:
        1、将所有的实际参数,返回地址等信息传递给被调函数予以保存;
        2、被调函数的局部变量(也包括形参)分配存储区;
        3、将控制转移到被调函数的入口。
被调函数返回给调用函数前,系统完成三件事:
        1、保存被调函数的计算结果;
        2、释放被调函数的数据区;
        3、依照被调函数保存的返回值地址,将控制权限转移给调用函数
多个函数调用时,后调用先返回
上述函数之间的传递及控制转移必须借助栈来实现。
调用函数时,在栈顶分配存储区;退出时,释放存储区。
当前正在运行的函数的数据区必须在栈顶。

调用10次,只分配一次代码空间


递归要满足的三个条件:
        1、递归必须有一个明确的终止条件;
        2、该函数所处理的数据规模必须在递减或递增;
        3、这个转化必须是可解的。


循环和递归的区别:
        递归:易于理解,速度慢,存储空间大(调用,发送地址、实参,花费时间)
        循环:不易理解,速度快,存储空间小


递归的应用:
        1、树和森林就是以递归的方式定义的
        2、树和图的很多算法以递归来实现
        3、数学公式
                    菲波拉契数列:1 2 3 5 8 13 21 34(当前数是前两位数之和)


简单例子(不同函数间的互相调用)

# include <stdio.h>

void f();
void g();
void k();

void f()
{
 printf("FFFF\n");
 g();
 printf("1111\n");
}

void g()
{
 printf("GGGG\n");
 k();
 printf("2222\n");
}

void k()
{
 printf("KKKK\n");
}

int main(void)
{
 f();

 return 0;
}



自我调用
# include <stdio.h>

/*
void f()
{
 printf("FFFF\n");
 f(); //溢栈时出错
}
*/

void f(int n)
{
 if(n == 1)
  printf("FFFF\n");
 else
  f(n-1);
}

int main(void)
{
 f(3);

 return 0;
}


间接调用
# include <stdio.h>

int f(int n)
{
 n += 2;
 return n;
}

int main(void)
{
 int val;

 val = f(5);
 printf("val = %d\n", val);

 return 0;
}



递归实例1 - 阶乘
1、求阶乘
方法一:循环
# include <stdio.h>

int main(void)
{
 int val;
 int i;
 int mult = 1;

 printf("pls input a number: ");
 printf("val= ");
 scanf("%d", &val);

 for (i=1; i<=val; ++i)
  mult = mult * i;

 printf("%d的阶乘是:%d!= %d\n", val, val, mult);
 
 return 0;
}

方法二:递归
# include <stdio.h>

long f(long n)
{
 if (1 == n)
  return 1;
 else
  return f(n-1) * n;
}

int main(void)
{
 int val;

 printf("pls intput a num: val = ");
 scanf("%d", &val);
 printf("%d的阶乘是:%d!= %ld\n", val, val, f(val));

 return 0;
}


递归求阶和
# include <stdio.h>

long sum(long n)
{
 if (1 == n)
  return 1;
 else
  return sum(n-1) + n;
}

int main(void)
{
 int val;

 printf("pls intput a num: val = ");
 scanf("%d", &val);
 printf("%d的阶和是:%d!= %ld\n", val, val, sum(val));

 return 0;
}


递归实例2 - 汉诺塔

# include <stdio.h>

void hannuota(int n, char A, char B, char C)
{
/*
 如果是1个盘子
  直接A移到C
 否则
  将A上的n-1个盘子借助C移动到B
  将A上的第n个盘子移到C
  将B上面的n-1个盘子借助A移到C
*/
 if (1 == n)
 {
  printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n", n, A, C);
 }
 else
 {
  hannuota(n-1, A, C, B);
  printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n", n, A, C);
  hannuota(n-1, B, A, C);

 }
}

int main(void)
{
 char ch1 = 'A';
 char ch2 = 'B';
 char ch3 = 'C';
 int n;

 printf("请输入要移动盘子的个数:");
 scanf("%d", &n);

 hannuota(n, 'A', 'B', 'C');

 return 0;
}


0 0
原创粉丝点击