AlgoVerse

برج‌های هانوی

n دیسک را از میله‌ی A به C می‌برد، هر بار یک دیسک و هیچ‌وقت دیسک بزرگ روی کوچک؛ دقیقاً 2ⁿ − 1 حرکت.

برای بردن k دیسک از میله‌ی مبدأ به مقصد:

ادامه‌ی توضیح ↓
ورودی:
n=3خروجی PDF

سه دیسک: ۷ حرکت.

  1. def hanoi(n):
  2. pegs = {"A": list(range(n, 0, -1)), "B": [], "C": []}
  3. moves = []
  4. solve(n, "A", "C", "B", pegs, moves)
  5. return moves
  6. def solve(k, src, dst, via, pegs, moves):
  7. if k == 0:
  8. return
  9. solve(k - 1, src, via, dst, pegs, moves)
  10. disk = pegs[src].pop()
  11. pegs[dst].append(disk)
  12. moves.append((disk, src, dst))
  13. solve(k - 1, via, dst, src, pegs, moves)

ناوردا: روی هر میله دیسک‌ها همیشه از بزرگ (پایین) به کوچک (بالا) چیده شده‌اند.

شروع اجرا

pegs—

جدول هنوز خالی است.

درخت فراخوانی‌های بازگشتی

نارنجی پر = فراخوانی در حال اجرا · حاشیه‌ی نارنجی = هنوز روی پشته · خاکستری = تمام شده

متغیرهای محلی

n3

نارنجی = در همین گام عوض شد

Call stack

  1. hanoi()خط 1
گام ۱ از ۷۸
خط سیاه = move · خط نارنجی = گام کلیدیmove: 0/7
    توضیح

    ایده

    برای بردن k دیسک از میله‌ی مبدأ به مقصد:

    1. k − 1 دیسک بالایی را (بازگشتی) به میله‌ی کمکی ببر؛
    2. بزرگ‌ترین دیسک را به مقصد ببر؛
    3. آن k − 1 دیسک را (بازگشتی) از میله‌ی کمکی روی آن بگذار.

    چند حرکت؟

    T(k) = 2·T(k−1) + 1 و T(0) = 0، پس T(n) = 2ⁿ − 1. ثابت می‌شود کمتر از این ممکن نیست: بزرگ‌ترین دیسک باید دست‌کم یک بار حرکت کند و قبلش همه‌ی بقیه باید کنار رفته باشند.

    در trace به چه چیزی نگاه کنی

    • کارت pegs وضعیت سه میله است (پایین به بالا) و جدول همه‌ی حرکت‌ها تا اینجا.
    • درخت فراخوانی‌ها درخت دودویی کاملی به عمق n است.
    • دیسک ۱ یک حرکت در میان حرکت می‌کند.