汉诺塔实现

#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);
		printf("paraSource:%p, paraDestination:%p, paraTransit:%p \r\n",&paraSource,&paraDestination,&paraTransit);
		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("---- addToTest ends. ----\r\n");
}
void main() {
	hanoiTest();
}

结果

1:自顶向下,逐渐求精,函数调用:

从最顶上的盘子开始移动,然后移动下面的盘子,用函数来表示这个过程

2:递归与分治(基础与归纳):

如果只有一个盘子在A柱上,只需直接移至C柱即可,否则需做以下步骤:

        1:用C柱做过渡,将A柱上的(n-1)个盘子移至B柱。

        2:将A柱上的最后一个盘子移至直接移至C柱。

        3:用A柱做过渡,将B柱上的(n-1)个盘子移至C柱上。

这样n个盘子变成了n-1个盘子的问题,依次这么进行下去,最终会变成一个盘子的问题。

3:不要跨层分析:

在分析的时候,我们头脑应该只有两个东西:A柱这一层待移动的盘子和下面所有未移动的盘子,如果将问题具体化去逐个分析下面的盘子,就会陷进去。

4:形参与实参:

在函数调用的过程中,系统会给传入的参数另外分配地址,形参所储存的东西与实参一样,但由于地址不同,改变形参并不能改变实参。

5:有意义,规范的标识符:

我们命名变量时候,不应该为了图方便而将变量名设置简单,这样其他人读不懂我们的代码,我们自己写了很多代码的时候也可能也会搞混变量的关系。

6:时间复杂度:

设盘子个数为n时,需要T(n)步,把A柱子(n-1)个盘子移到B柱子,需要T(n-1)步,A柱子最后一个盘子移到C柱子一步,B柱子上n-1个盘子移到C柱子上T(n-1)步。
得递推公式T(n)= 2 * T(n-1) + 1
所以汉诺塔问题的时间复杂度为O(2^n);

7:递归栈:

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 100  //定义栈的最大大小

typedef struct
{
    int top;  //栈顶指针
    int data[MAXSIZE];  //栈的数据
} Stack;

// 初始化栈
void init(Stack *s)
{
    s->top = -1;
}

// 判断栈是否为空
int isEmpty(Stack *s)
{
    return s->top == -1;
}

// 判断栈是否已满
int isFull(Stack *s)
{
    return s->top == MAXSIZE - 1;
}

// 入栈操作
void push(Stack *s, int item)
{
    if (isFull(s))
    {
        printf("栈已满\n");
        return;
    }
    s->data[++s->top] = item;
}

// 出栈操作
int pop(Stack *s)
{
    if (isEmpty(s))
    {
        printf("栈已空\n");
        return -1;
    }
    return s->data[s->top--];
}

// 汉诺塔递归函数,n表示盘子数量,A、B、C分别表示三个柱子
void hanoi(int n, Stack *A, Stack *B, Stack *C)
{
    if (n == 1)
    {
        push(C, pop(A));  // 将A柱子顶部的盘子移动到C柱子
    }
    else
    {
        hanoi(n - 1, A, C, B);  // 将A柱子的前n-1个盘子通过C柱子移动到B柱子
        push(C, pop(A));  // 将A柱子剩下的一个盘子移动到C柱子
        hanoi(n - 1, B, A, C);  // 将B柱子上的n-1个盘子通过A柱子移动到C柱子
    }
}

int main()
{
    int n=8;  //盘子数量
    Stack A, B, C;  //定义三个栈分别表示三个柱子
    init(&A);
    init(&B);
    init(&C);

    for (int i = n; i >= 1; i--)
    {
        push(&A, i);
    }

    // 进行汉诺塔移动
    hanoi(n, &A, &B, &C);

    return 0;
}

8:空间复杂度:     

通过用栈实现汉诺塔问题,很容易知道其复杂度为O(n)。

通过学习,我了解了递归的奇妙之处,并且学会了如何去分析递归的空间和时间复杂度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值