数据结构作业之栈递归

递归

程序调用自身的编程技巧称为递归( recursion)。递归作为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

累加的递归实现

本代码相对简单,不做进一步说明,在老师代码的基础上加入了少量的格式内容方便查看结果。

#include <stdio.h>

/**
 * 递归加法
 */
int addTo(int paraN){
    int tempSum;
    printf("entering addTo(%d)\r\n",paraN);
    if(paraN<=0){
        printf(" return 0\r\n");
        return 0;
    }else{
        tempSum = addTo(paraN-1)+paraN;
        printf(" return %d\r\n",tempSum);
        return tempSum;
    }
}

/**
 * 函数功能测试
 */
void addToTest(){
    int n,sum;
    printf("---- addToTest begins. ----\r\n");

    n=5;
    sum = addTo(n);
    printf("\r\n0 adds to %d gets %d.\r\n",n,sum);
    printf("----------------------\r\n");

    n=1;
    sum = addTo(n);
    printf("\r\n0 adds to %d gets %d.\r\n",n,sum);
    printf("----------------------\r\n");

    n=-1;
    sum = addTo(n);
    printf("\r\n0 adds to %d gets %d.\r\n",n,sum);
    printf("----------------------\r\n");

    printf("---- addToTest ends. ----\r\n");
}

/**
 * 程序入口
 */
void main(){
    addToTest();
}

测试结果:

---- addToTest begins. ----
entering addTo(5)
entering addTo(4)
entering addTo(3)
entering addTo(2)
entering addTo(1)
entering addTo(0)
 return 0
 return 1
 return 3
 return 6
 return 10
 return 15

0 adds to 5 gets 15.
----------------------
entering addTo(1)
entering addTo(0)
 return 0
 return 1

0 adds to 1 gets 1.
----------------------
entering addTo(-1)
 return 0

0 adds to -1 gets 0.
----------------------
---- addToTest ends. ----

递归实现汉诺塔问题

汉诺塔问题源自印度一个古老的传说,印度教的“创造之神”梵天创造世界时做了 3 根金刚石柱,其中的一根柱子上按照从小到大的顺序摞着 64 个黄金圆盘。梵天命令一个叫婆罗门的门徒将所有的圆盘移动到另一个柱子上,移动过程中必须遵守以下规则:

  • 每次只能移动柱子最顶端的一个圆盘;
  • 每个柱子上,小圆盘永远要位于大圆盘之上;

 

问题分析:

把大象放进冰箱需要几步:

  1. 打开冰箱
  2. 把大象放进去
  3. 把冰箱门关上

把a柱的n个盘子移动到c柱需要几步:

  1. 把前n-1个盘子都移动到b柱
  2. 把最大的盘子(第n个)移动到c柱
  3. 把b柱上的n-1个盘子移动到c柱
    如下

 如果直接想全部n个的过程我们是比较难以想象的,但是因为递归的特性,我们只需写出第n个移动顺序即可。

void hanoi(int paraN, char paraSource, char paraDestination, char paraTransit) {
	if (paraN <= 0) {
		return;
	} else {
		hanoi(paraN - 1, paraSource, paraTransit, paraDestination);
		printf("%c -> %c \r\n", paraSource, paraDestination);
		hanoi(paraN - 1, paraTransit, paraDestination, paraSource);
	}
}

按照第n部的理解,我们需要先将小的块从a移到Transit,在将大的盘子移到Destination,最后将Transit的盘子移动到Destina,即上图的部分,最后推广到递归中,逐次将n减少,等到最终的函数。

汉诺塔问题的时间复杂度为O(2^n),空间复杂度为O(n)。

完整代码

#include <stdio.h>

/**
 * 汉诺塔问题
 */
void hanoi(int paraN, char paraSource, char paraDestination, char paraTransit) {
	if (paraN <= 0) {
		return;
	} else {
		hanoi(paraN - 1, paraSource, paraTransit, paraDestination);
		printf("%c -> %c \r\n", paraSource, paraDestination);
		hanoi(paraN - 1, paraTransit, paraDestination, paraSource);
	}
}

/**
 * 测试函数功能
 */
void hanoiTest() {
    printf("---- addToTest begins. ----\r\n");

	printf("2 plates\r\n");
	hanoi(2, 'A', 'B', 'C');

	printf("3 plates\r\n");
	hanoi(3, 'A', 'B', 'C');

    printf("4 plates\r\n");
	hanoi(4, 'A', 'B', 'C');

    printf("---- addToTest ends. ----\r\n");
}

/**
 * 程序入口
 */
void main() {
	hanoiTest();
}

测试结果:

 ---- addToTest begins. ----
2 plates
A -> C
A -> B
C -> B
3 plates
A -> B
A -> C
B -> C
A -> B
C -> A
C -> B
A -> B
4 plates
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
---- addToTest ends. ----

总结

递归问题的关键在于找出最外层的函数规律。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值