欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构 - 递归(汉诺塔)

程序员文章站 2024-03-16 16:10:04
...

一、调用 collections 中的 deque(双端链表)实现递归的栈操作

# 用栈模拟递归调用

# 调用双端列表
from collections import deque

class Stack:

    def __init__(self):
        self._deque = deque()

    # 调用 deque 中的 append 方法
    def push(self,value):
        return self._deque.append(value)

    # 调用 duque 中的 pop 方法
    def pop(self):
        return self._deque.pop()

    # 出栈条件,不不为空则 pop
    def is_empty(self):
        return len(self._deque) == 0


def print_num_use_stack(n):
    s = Stack()

    # 入栈
    while n > 0:
        s.push(n)
        n -= 1

    # 出栈
    while not s.is_empty():
        print(s.pop())

def test():
    print_num_use_stack(10)

test()

二、尾递归
尾递归将递归调用放在了函数的最后。因为普通递归的每一机递归都产生了新的局部变量,必须创建新的调用栈,随着递归深度的增加,创建的栈越来越多,造成爆栈。优化可使尾递归的每一级调用公用一个栈。

def print_num_recursive(n):
    if n > 0:
        pring(n)
        print_num_recursive(n-1)

三、汉诺塔问题

def HanoiMove(n, source, dest, intermediate):
    if n >= 1:  # 递归出口,只剩一个盘子
        HanoiMove(n - 1, source, intermediate, dest)
        print("Move %s -> %s" % (source, dest))
        HanoiMove(n - 1, intermediate, dest, source)


HanoiMove(3, 'A', 'C', 'B')

解析:汉诺塔问题是一个典型的递归问题。设有 A、B、C杆分别是原始杆、中转杆和目标杆,要将A杆的盘都挪到C杆上。将问题划分为如下两个操作:

(1)只留下最大的盘,其余盘挪到B杆,将其看作一个整体,具体怎么挪先不管;可以得到挪动单个盘的操作:A➡️C
(2)将B杆上的这些盘看作一个整体挪动到C杆上,完成挪动。

递归操作(1),完成的是:由 A-目标杆 将 n-1 个盘挪到 B-中转杆
递归操作(2),完成的事:由 B-中转杆 将 n-1 个盘挪到 C-目标杆

通过逆向的递归方法即可完成将所有盘由 A 挪到 C 的操作。