數據結構:遞歸:漢諾塔問題(Tower of Hanoi)

目錄

問題描述

?第一性原理分析

代碼實現

第一步:明確函數要干什么

第二步:寫好遞歸的“結束條件”

第三步:寫遞歸步驟?

?🌳 遞歸調用樹

🔍復雜度分析

時間復雜度:T(n) = 2^n - 1

?空間復雜度分析


問題描述

有三個柱子(A, B, C),上面有 n 個大小不等的圓盤,最開始所有圓盤按從大到小順序堆在柱子 A 上。
目標:將所有圓盤移動到柱子 C,移動時要滿足:

  1. 一次只能移動一個盤子;

  2. 任何時刻小盤子不能壓在大盤子上。

?核心問題:

如何將 n 個盤子 從 A 移動到 C,同時只用 B 做輔助,且不違反約束?

?第一性原理分析

🔹1.基礎情況(Base Case)

  • n = 1:只有一個盤子,直接從 A → C,一步解決。這是最小子問題。

🔹2. 如果有兩個盤子,要怎么動?

設柱子為 A(起始)、B(輔助)、C(目標):

你會這樣操作:

  1. 把小盤子從 A → B

  2. 把大盤子從 A → C

  3. 再把小盤子從 B → C

?🔹3. 如果有三個盤子,要怎么動?

步驟 1:移動盤子 1 從 A ? C

步驟 2:移動盤子 2 從 A ? B

步驟 3:移動盤子 1 從 C ? B

步驟 4:移動盤子 3 從 A ? C???????

步驟 5:移動盤子 1 從 B ? A

步驟 6:移動盤子 2 從 B ? C???????

步驟 7:移動盤子 1 從 A ? C???????

這就引出一個關鍵邏輯:

? 要移動第 n 個(最大)盤子,必須先把上面的 n-1 個盤子“暫時”搬開。

🧩 移動 n 個盤子的本質是 —— 找出一個“序列”,讓我們可以先清掉上面的 n-1 個盤子,再移動第 n 個,然后再恢復那 n-1 個。

換句話說:

  • n-1 個盤子移到輔助柱;

  • 把第 n 個(最大)盤子移到目標柱;

  • 再把那 n-1 個盤子從輔助柱移回來。

這三步操作可以形成遞歸:

Hanoi(n, A, B, C):1. 移動 n-1 個盤子從 A → B(借助 C)Hanoi(n-1, A, C, B)2. 移動第 n 個盤子從 A → C3. 移動 n-1 個盤子從 B → C(借助 A)Hanoi(n-1, B, A, C)

📐 所以從第一性來看,漢諾塔的“遞歸”,不是魔法,而是邏輯:

  • 沒有任何一步是“看上去神奇的”;

  • 每一個盤子的移動,都必須建立在“先讓出空間”的原則上;

  • 這就導致了問題具有自相似性:每一層和上面那一層的問題結構一樣;

原理對應在漢諾塔問題的體現
?本質原子操作移動一個盤子,必須遵守限制
?問題的自相似性每個子問題與原問題結構完全一樣 ? 遞歸自然產生
?從底向上構建解決結構不依賴公式,從 n = 1 出發,構建到 n = 2, 3...

代碼實現

第一步:明確函數要干什么

我們要寫的是一個函數:移動 n 個盤子從柱子 A → 柱子 C,借助柱子 B。

?所以我們需要:

  • 盤子的數量:int n

  • 三個柱子的名字(我們用字符):char from, temp, to

#include <iostream>
using namespace std;// 函數聲明:移動 n 個盤子,從 from → to,借助 temp
void hanoi(int n, char from, char temp, char to) {

解釋:

  • n:要移動的盤子數

  • from:起始柱

  • temp:中轉柱(輔助)

  • to:目標柱

第二步:寫好遞歸的“結束條件”

為什么要加“終止條件”?

如果你不加,遞歸會無限下去,直到程序崩潰!

    if (n == 1) {cout << "Move disk 1 from " << from << " to " << to << endl;return;}

解釋:

  • 如果只剩一個盤子,那就是最簡單的情況,直接從 fromto

  • cout 是打印這一步。

第三步:寫遞歸步驟?

    // 1. 把 n-1 個盤子從 from → temp,借助 tohanoi(n - 1, from, to, temp);// 2. 把第 n 個盤子從 from → tocout << "Move disk " << n << " from " << from << " to " << to << endl;// 3. 把 n-1 個盤子從 temp → to,借助 fromhanoi(n - 1, temp, from, to);
}

分析這三步邏輯:

  1. 把頂部的 n-1 個盤子先“挪走”(遞歸調用自己);

  2. 把第 n 個盤子(最大的)真正地移動到底部(打印出來);

  3. 把剛才挪走的 n-1 個盤子搬回來(遞歸調用自己)。

完整代碼

#include <iostream>
using namespace std;// 遞歸函數:將 n 個盤子從 from 移動到 to,借助 temp
void hanoi(int n, char from, char temp, char to) {if (n == 1) {cout << "Move disk 1 from " << from << " to " << to << endl;return;}// 第一步:把 n-1 個盤子從 from → temphanoi(n - 1, from, to, temp);// 第二步:移動第 n 個盤子到目標柱cout << "Move disk " << n << " from " << from << " to " << to << endl;// 第三步:把 n-1 個盤子從 temp → tohanoi(n - 1, temp, from, to);
}int main() {int n;cout << "Enter number of disks: ";cin >> n;hanoi(n, 'A', 'B', 'C');return 0;
}

?🌳 遞歸調用樹

我們現在來畫出 hanoi(3, A, B, C) 的調用樹結構,說明遞歸是怎么層層展開的。

                            hanoi(3, A, B, C)/         |         \hanoi(2, A, C, B)     Move 3     hanoi(2, B, A, C)/     |     \                       /     |     \hanoi(1,A,B,C)  M2  hanoi(1,C,A,B)   hanoi(1,B,C,A)  M2  hanoi(1,A,B,C)

?標上實際操作編號:

                            hanoi(3, A, B, C)/         |         \hanoi(2, A, C, B)     Move 3     hanoi(2, B, A, C)/     |     \                       /     |     \hanoi(1,A,B,C)  M2  hanoi(1,C,A,B)   hanoi(1,B,C,A)  M2  hanoi(1,A,B,C)/          |         \          |         /          |         \
step1         step2    step3      step4    step5     step6       step7
調用操作內容ABC
hanoi(3, A, B, C)主函數入口[3, 2, 1][][]
hanoi(2, A, C, B)把上面兩個盤子從 A ? B
hanoi(1, A, B, C)直接移動盤子 1
Move disk 1 A→CStep 1[3, 2][][1]
Move disk 2 A→BStep 2[3][2][1]
Move disk 1 C→BStep 3[3][2, 1][]
Move disk 3 A→CStep 4[][2, 1][3]
hanoi(2, B, A, C)把兩個盤子從 B ? C
Move disk 1 B→AStep 5[1][2][3]
Move disk 2 B→CStep 6[1][][3, 2]
Move disk 1 A→CStep 7[][][3, 2, 1]

🔍復雜度分析

時間復雜度:T(n) = 2^n - 1

漢諾塔的遞歸形式是這樣的:

T(n) = 2 * T(n - 1) + 1

意思是:

  • 為了移動 n 個盤子:

    • 我們要先移動 n - 1 個盤子(第一次調用);

    • 移動第 n 個盤子(+1 次);

    • 再移動 n - 1 個盤子(第二次調用)。

利用迭代展開式來看:

T(n) = 2*T(n-1) + 1= 2*(2*T(n-2) + 1) + 1 = 4*T(n-2) + 2 + 1= 8*T(n-3) + 4 + 2 + 1= ...= 2^k * T(n - k) + (2^(k-1) + ... + 2 + 1)

?當 k = n-1 時,T(1) = 1,代入得到:

T(n) = 2^(n - 1) * T(1) + (2^(n - 2) + ... + 1)= 2^(n - 1) * 1 + (2^(n - 1) - 1)= 2^n - 1

所以時間復雜度是:?? T(n) = O(2^n)

也就是說:

  • 每增加一個盤子,所需的移動次數翻倍 + 1。

  • 極其不可擴展。

?空間復雜度分析

我們來看遞歸函數會“開多少層棧”:

void hanoi(int n, char from, char temp, char to)
{if (n == 1) return;hanoi(n - 1, from, to, temp); // 一次遞歸調用// move...hanoi(n - 1, temp, from, to); // 第二次遞歸調用
}

遞歸深度分析:

  • 最大的遞歸深度就是從 nn-1n-2 → ... → 1

  • 所以最多開 n 層函數棧

所以空間復雜度是:🧠 Space: O(n)

  • 因為遞歸是深度優先遍歷

  • 不會存儲所有子問題,只保存當前路徑

🕊? 如果你是“神廟僧侶”,每天只移動 1 次?

漢諾塔在傳說中是:64 個金盤子,僧侶每天移動一塊。

T(64) = 2^64 - 1 ≈ 1.84 × 10^19 次

即使 1 秒動一次,你也需要:

≈ 5.8 × 10^11 年

而宇宙年齡都才 138 億年。所以說移動 64?個盤子“永遠也完成不了”。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/912798.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/912798.shtml
英文地址,請注明出處:http://en.pswp.cn/news/912798.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

synetworkflowopenrestydpdk

一.skynet 1. Skynet 的核心架構是什么&#xff1f;簡述其進程與服務模型。 Skynet 采用多進程多服務架構。主進程負責管理和監控&#xff0c;多個工作進程&#xff08;worker&#xff09;負責實際服務運行。每個服務&#xff08;service&#xff09;是一個獨立的 Lua 虛擬機&…

【甲方安全視角】安全防御體系建設

文章目錄 前言一、云安全防護能力第一階段:搭建安全防護設施第二階段:安全防護設施的精細化運營第三階段:安全運營周報輸出二、IT安全防護能力(一)辦公網安全設施建設(二)辦公網安全運營三、基礎安全防護能力(一)物理安全(二)運維安全(三)安全應急響應四、總結前言…

計算機組成原理與體系結構-實驗一 進位加法器(Proteus 8.15)

目錄 一、實驗目的 二、實驗內容 三、實驗器件 四、實驗原理 4.1 行波進位加法器 4.2 先行進位加法器 4.3 選擇進位加法器&#xff08;嘗試猜測原理&#xff09; 五、實驗步驟與思考題 一、實驗目的 1、了解半加器和全加器的電路結構。 2、掌握串行進位加法器和并行進…

react+antd Table實現列拖拽,列拉寬,自定義拉寬列

主要插件Resizable&#xff0c;dnd-kit/core&#xff0c;dnd-kit/sortable&#xff0c;dnd-kit/modifiers 其中官網有列拖拽&#xff0c;主要結合Resizable 實現列拉寬&#xff0c;isResizingRef 很重要防止拖拽相互影響 1.修改TableHeaderCell const isResizingRef useRef(…

光照解耦和重照明

項目地址&#xff1a; GitHub - NJU-3DV/Relightable3DGaussian&#xff1a; [ECCV2024] 可重新照明的 3D 高斯&#xff1a;使用 BRDF 分解和光線追蹤的實時點云重新照明 可優化參數 gaussians.training_setup(opt) if is_pbr:&#xff1a; direct_env_light.training_setup…

Kafka 運維與調優篇:構建高可用生產環境的實戰指南

&#x1f6e0;? Kafka 運維與調優篇&#xff1a;構建高可用生產環境的實戰指南 導語&#xff1a;在生產環境中&#xff0c;Kafka集群的穩定運行和高性能表現是業務成功的關鍵。本篇將深入探討Kafka運維與調優的核心技術&#xff0c;從監控管理到性能優化&#xff0c;再到故障排…

AR 地產互動沙盤:為地產沙盤帶來變革?

在科技飛速發展的今天&#xff0c;AR&#xff08;增強現實&#xff09;技術應運而生&#xff0c;為解決傳統地產沙盤的困境提供了全新的思路和方法。AR 技術&#xff0c;簡單來說&#xff0c;是一種將計算機生成的虛擬信息與真實環境相融合的技術。它通過攝像頭、傳感器等設備獲…

端到端自動駕駛系統關鍵技術

一、感知決策一體化模型架構 單一神經網絡整合全流程 端到端神經網絡能夠直接將傳感器輸入映射為控制輸出&#xff0c;消除了傳統模塊化架構中感知、規劃、控制等獨立模塊之間的割裂。傳統架構中&#xff0c;感知模塊負責識別環境信息&#xff0c;決策模塊根據感知結果進行路…

Vue Vue-route (2)

Vue 漸進式JavaScript 框架 基于Vue2的學習筆記 - Vue-route重定向和聲明式導航 目錄 Vue-route路由 重定向 首頁默認訪問 不存在匹配 聲明式導航 路由原理 使用示例 自定義class類 Tag設置 版本4路由 改變 示例 總結 Vue-route路由 重定向 首頁默認訪問 希望訪…

Mabl 基于云端的智能化自動化測試平臺

??親愛的技術愛好者們,熱烈歡迎來到 Kant2048 的博客!我是 Thomas Kant,很開心能在CSDN上與你們相遇~?? 本博客的精華專欄: 【自動化測試】 【測試經驗】 【人工智能】 【Python】 </

Linux/Dog

Dog Enumeration nmap 第一次掃描發現系統對外開放了22、80端口&#xff0c;端口詳細信息如下 ┌──(kali?kali)-[~/Desktop/vegetable/HTB] └─$ nmap -sC -sV -p 22,80 -oA nmap 10.10.11.58 Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-26 03:36 EDT Nmap s…

青少年編程與數學 02-022 專業應用軟件簡介 01 設計與創意類軟件:Adobe Creative Cloud

青少年編程與數學 02-022 專業應用軟件簡介 01 設計與創意類軟件&#xff1a;Adobe Creative Cloud **一、Adobe公司介紹**&#xff08;一&#xff09;Adobe的創立與早期發展&#xff08;二&#xff09;Adobe的市場地位與影響力&#xff08;三&#xff09;Adobe的創新文化 **二…

【亞馬遜防關聯攻略】多店鋪運營如何做好環境隔離?

在亞馬遜跨境電商中&#xff0c;多店運營的最大風險是賬號關聯。亞馬遜規定&#xff0c;同一賣家在同一站點只能擁有一個店鋪。平臺會通過多種方式追蹤注冊信息、設備和網絡環境等&#xff0c;如果發現關聯因素&#xff0c;所有關聯賬號可能被批量封禁&#xff0c;這會導致資金…

She‘s Coming !

#好書推薦《一本書講透汽車功能安全&#xff1a;標準詳解與應用實踐》 #功能安全應用指南 #功能安全實踐參考寶典 Finally, shes coming ! 她來得有點晚&#xff0c;但 “好飯不怕晚”。 她就是剛出爐的新書《一本書講透汽車功能安全&#xff1a;標準詳解與應用實踐》 京東…

如何用廢棄電腦變成服務器搭建web網站(公網訪問零成本)

文章目錄 &#x1f4bb; 如何用廢棄電腦變成服務器搭建 Web 網站&#xff08;公網訪問零成本&#xff09;一、背景與目標? 本文目標&#xff1a; 二、準備工作&#xff08;軟硬件需求&#xff09;&#x1f9f1; 1. 硬件需求&#x1f9f0; 2. 軟件環境準備 三、快速搭建一個 Fl…

〔從零搭建〕指標體系平臺部署指南

&#x1f525;&#x1f525; AllData大數據產品是可定義數據中臺&#xff0c;以數據平臺為底座&#xff0c;以數據中臺為橋梁&#xff0c;以機器學習平臺為中層框架&#xff0c;以大模型應用為上游產品&#xff0c;提供全鏈路數字化解決方案。 ?杭州奧零數據科技官網&#xf…

Vue3 中watch和computed

Vue 3 中 computed 與 watch 深度解析 在 Vue 3 組合中&#xff0c;響應式工具的類型安全使用至關重要。以下是詳細說明 一、watch 偵聽器 1. 基礎類型監聽 <template><div>實際參數1{{count}}</div><div><button click"count">點…

.NET測試工具Parasoft dotTEST:全兼容RMS的測試解決方案

隨著項目規模擴大&#xff0c;需求管理變得復雜&#xff0c;如何高效追溯需求與測試的關聯性成為一大挑戰。Parasoft dotTEST 提供了一套強大的需求追溯解決方案&#xff0c;不僅能自動關聯單元測試結果與需求&#xff0c;還能兼容幾乎所有需求管理系統&#xff08;RMS&#xf…

基于Jeecgboot3.8.1的vue3版本前后端分離的flowable流程管理平臺

初步遷移完成了基于jeecgboot3.8.1的vue3版本的前后端流程管理平臺,基于flowable6.8.0,同時支持bpmn流程設計器與仿釘釘流程設計器。 功能類似于3.6.3,但增加了一些以下功能: 1、支持多租戶 2、支持并行網關的任意跳轉、退回與駁回 3、流程表達式 這里流程表達式定義四…

IP 限流 vs. URI 限流

背景&#xff1a; 昨天調程序的時候遇到了一個 BUG&#xff0c;前端無法將文件正確傳給后端&#xff0c;后端報錯 EOFException&#xff08;EOF 代表 End Of File&#xff09;就是在程序嘗試從一個數據流中讀取數據時&#xff0c;發現已經到達了數據流的末尾&#xff0c;但它卻…