当前位置: 首页 > news >正文

数据结构(c++版):二叉树的实现

让我们走进"二叉树童话王国",用生活中的故事理解每一个代码概念!

📚 第一章:书架的魔法格子——节点结构体

template<typename T>
struct treeNode
{T data;                // 格子里藏的宝物treeNode<T>* left;     // 左边的魔法门treeNode<T>* right;    // 右边的魔法门treeNode() :data(0), left(NULL), right(NULL) {};      // 空空的初始格子treeNode(T d) :data(d), left(NULL), right(NULL) {};   // 放入宝物的格子
};

🏰 城堡里的宝物格子

想象一座魔法城堡,每个房间都有一个特殊的宝物格子:

  • data​:格子里藏的宝物(可能是金苹果、魔法书或水晶球)
  • left​:左边的魔法门,通向比当前宝物"年龄小"的宝物房间
  • right​:右边的魔法门,通向比当前宝物"年龄大"的宝物房间

🧙♂️ ​老巫师的两种魔法​:

  1. treeNode():创造一个空空的宝物格子(还没放入任何宝物)
  2. treeNode(T d):创造一个已经放入宝物d的格子

就像城堡管家说:"第7号宝物格子放着'金苹果',它左边的门通向3号房间,右边的门通向11号房间"

🏛️ 第二章:整个魔法城堡——二叉树类

template<typename T>
class Tree
{
private: treeNode<T>* nodes;    // 城堡所有房间的登记簿treeNode<T>* root;     // 城堡的主入口size_t nodesize;       // 城堡总房间数treeNode<T>* creat(T a[], int size, int nodeId, T nullNode);void visit(treeNode<T>* node);  // 参观一个宝物房间void preOrder(treeNode<T>* node);void inOrder(treeNode<T>* node);void postOrder(treeNode<T>* node);public:Tree();Tree(int maxidex);~Tree();treeNode<T>* Gertreenode(int Id);void creatTree(T a[], int size, T nullNode);void preorder();   // 探险路线1:先看当前,再看左右void inorder();    // 探险路线2:先看左,再看当前,最后右void postorder();  // 探险路线3:先看左右,最后看当前
};

🏯 魔法城堡的构造

  • nodes​:城堡所有房间的登记簿(记录每个房间的位置和内容)
  • root​:城堡的主入口大门(从这里开始探险)
  • nodesize​:城堡总共有多少个房间

🗝️ 城堡的三种探险路线

  1. preorder​:勇者路线(先看当前宝物,再探索左右)
  2. inorder​:学者路线(按宝物年龄顺序探索)
  3. postorder​:清洁工路线(从最远的房间开始打扫)

🏗️ 第三章:建造与拆除城堡——构造与析构

// 默认建造能容纳100000个宝物的大城堡
template<typename T>
Tree<T>::Tree() { nodes = new treeNode<T>[100000]; }// 按国王的要求建造特定大小的城堡
template<typename T>
Tree<T>::Tree(int maxindex) { nodes = new treeNode<T>[maxindex]; }// 拆除城堡(当王国灭亡时)
template<typename T>
Tree<T>::~Tree() { delete[]nodes; }

👑 国王的建造令

  1. 默认城堡​:当国王没说具体大小时,建一个能放100000个宝物的大城堡(Tree()
  2. 定制城堡​:当国王说"我要一个能放maxindex个宝物的城堡"(Tree(int maxindex)
  3. 拆除城堡​:当王国灭亡时,拆除整个城堡释放土地(~Tree()

就像建筑大臣说:"陛下,按您的要求,我们建造了一个有15个宝物房间的城堡!"

🗺️ 第四章:布置城堡房间——创建树

void Tree<T>::creatTree(T a[], int size, T nullNode) {root = creat(a, size, 1, nullNode); // 从1号主殿开始布置
}treeNode<T>* Tree<T>::creat(T a[], int size, int nodeId, T nullNode) {if (nodeId >= size || a[nodeId] == nullNode) {return NULL; // 这个位置不设宝物房间}treeNode<T>* nownode = Gertreenode(nodeId); // 找到这个房间nownode->data = a[nodeId]; // 放入宝物// 布置左边的房间(编号是当前的两倍)nownode->left = creat(a, size, 2 * nodeId, nullNode);// 布置右边的房间(编号是当前的两倍加一)nownode->right = creat(a, size, 2 * nodeId+1, nullNode);return nownode; // 返回布置好的房间
}

🧭 城堡布局规则

  1. 主殿​:1号房间是城堡的主入口(root)
  2. 左翼​:每个房间n的左房间是2n号
  3. 右翼​:每个房间n的右房间是2n+1号
  4. 空房间​:如果设计图上标记nullNode(如'-'),就不布置这个房间

🏗️ ​布置过程​:

拜访顺序​:a → b → d → g → h → c → e → f → i

就像一位有礼貌的客人,每到一家都先问候最年长的主人,然后再去见他的孩子们。

第二把钥匙:🗝️ "年龄顺序"钥匙(中序遍历)

void inOrder(treeNode<T>* node) {if (node) {inOrder(node->left);  // 先拜访所有左边的晚辈visit(node);          // 然后问候当前长辈inOrder(node->right); // 最后拜访右边的晚辈}
}

拜访故事​:
族长a说:"这把钥匙的访客很讲究顺序,他们从最年轻的开始拜访,最后才来见我这位最年长的。"

拜访路线:

拜访顺序​:g → d → h → b → a → e → c → i → f

就像整理家族相册,从最年轻的婴儿照片开始,慢慢看到最年长的祖辈照片。

第三把钥匙:🗝️ "晚辈优先"钥匙(后序遍历)

void postOrder(treeNode<T>* node) {if (node) {postOrder(node->left);  // 先拜访所有左边的晚辈postOrder(node->right); // 然后拜访右边的晚辈visit(node);            // 最后问候当前长辈}
}

拜访故事​:
族长a笑着说:"这把钥匙的访客最有耐心,他们要把所有孩子都见完了,最后才来见我这位老祖宗。"

拜访路线:

拜访顺序​:g → h → d → b → e → i → f → c → a

就像发压岁钱,必须先给最小的孩子发完,最后才给最年长的长辈。

🌟 魔法钥匙的现实应用

🎄 圣诞节礼物配送(前序遍历)

圣诞老人用"族长优先"钥匙:

📚 图书馆整理书籍(中序遍历)

图书管理员用"年龄顺序"钥匙:

🧹 大扫除顺序(后序遍历)

清洁工用"晚辈优先"钥匙:

🎯 验证我们的魔法探险

int main() {const char nullNode = '-';char a[16] = {'-','a','b','c','d','-','e','f','g','h','-','-','i','-','-','-'};Tree<char> magicTree(16);magicTree.creatTree(a, 16, nullNode);cout << "族长优先钥匙: ";magicTree.preorder(); cout << endl;  // abdghceficout << "年龄顺序钥匙: ";magicTree.inorder(); cout << endl;   // gdhbaecifcout << "晚辈优先钥匙: ";magicTree.postorder(); cout << endl; // ghdbeifcareturn 0;
}

运行结果完全匹配我们的探险故事!​​ 🎉

💫 魔法森林的智慧

通过这次魔法森林的探险,我们学到了:

记住这个魔法口诀:

下次当你需要遍历一棵树时,就想想这座魔法森林,选择适合的钥匙来开启你的探险之旅!

  • 管家拿着设计图(a[])走遍城堡
  • 在1号主殿放入宝物'A'
  • 然后去2号(1×2)左殿放宝物'B'
  • 再去3号(1×2+1)右殿放宝物'C'
  • 遇到'-'就跳过不布置
  • 🌳 二叉树探险记:三把神奇钥匙打开魔法森林 🌳

    想象一下,你面前有一座神秘的魔法森林,里面住着9个会说话的字魔法精灵:a、b、c、d、e、f、g、h、i。它们住在一棵神奇的家族树屋里,每个精灵都有自己的房间,房间之间用魔法楼梯相连。

    🏰 魔法树屋的建造蓝图

    char a[16] = {'-',   // 0号位置:地基,不建房'a',   // 1号:族长爷爷a的顶层套房'b',   // 2号:大儿子b的房间'c',   // 3号:二儿子c的房间  'd',   // 4号:孙子d的房间(b的孩子)'-',   // 5号:空房间(b的另一个孩子出国了)'e',   // 6号:孙子e的房间(c的孩子)'f',   // 7号:孙子f的房间(c的另一个孩子)'g',   // 8号:曾孙g的房间(d的孩子)'h',   // 9号:曾孙h的房间(d的另一个孩子)'-',   // 10号:空房间'-',   // 11号:空房间'i',   // 12号:曾孙i的房间(f的孩子)'-',   // 13号:空房间'-',   // 14号:空房间'-'    // 15号:空房间
    };
            族长a(顶层)/      \儿子b     儿子c/        /   \孙子d    孙子e  孙子f/   \           /
    曾孙g  曾孙h     曾孙i

    🔑 三把神奇的拜访钥匙

    森林守护者给了我们三把不同的魔法钥匙,每把钥匙都对应一种特殊的拜访顺序:

    第一把钥匙:🗝️ "族长优先"钥匙(前序遍历)

    void preOrder(treeNode<T>* node) {if(node) {visit(node);          // 先拜访当前房间的精灵preOrder(node->left);  // 然后探索左边的所有子孙preOrder(node->right); // 最后探索右边的所有子孙}
    }

    拜访故事​:
    族长爷爷a说:"用这把钥匙的访客都很尊重长辈,他们总是先来拜访我!"

    拜访路线:

  • 🎯 先敲族长a的门:"爷爷好!"
  • 📍 然后去左边找儿子b:"b叔叔好!"
  • 📍 b说:"先去见我左边的孩子d"
  • 📍 d说:"先见我左边的g"
  • 👶 见到g:"g小朋友好!"
  • 📍 回到d:"现在见我右边的h"
  • 👶 见到h:"h小朋友好!"
  • 🔄 回到族长a:"左边的都拜访完了,现在去右边"
  • 📍 找儿子c:"c叔叔好!"
  • 📍 c说:"先见我左边的e"
  • 👶 见到e:"e小朋友好!"
  • 📍 c说:"现在见我右边的f"
  • 📍 f说:"先见我左边的i"
  • 👶 见到i:"i小朋友好!"
  • 🔍 从族长a开始,但先不敲门
  • 📍 去找最左边的g(最小的曾孙)
  • 👶 敲门:"g小朋友好!"
  • ↩️ 回到g的爸爸d:"d叔叔好!"
  • 📍 d说:"现在去见我右边的h"
  • 👶 见到h:"h小朋友好!"
  • ↩️ 回到d的爸爸b:"b爷爷好!"
  • ↩️ 回到族长a:"族长爷爷好!"
  • 📍 a说:"现在去右边找e"
  • 👶 见到e:"e小朋友好!"
  • ↩️ 回到e的爸爸c:"c爷爷好!"
  • 📍 c说:"现在去见我右边的f"
  • 📍 f说:"先见我左边的i"
  • 👶 见到i:"i小朋友好!"
  • ↩️ 回到f:"f叔叔好!"
  • 🔍 从族长a开始,但忍着不敲门
  • 📍 先找到最左边的g
  • 👶 敲门:"g小朋友好!"
  • 📍 然后找g的兄弟h
  • 👶 敲门:"h小朋友好!"
  • ↩️ 回到g和h的爸爸d:"d叔叔好!"
  • ↩️ 回到d的爸爸b:"b爷爷好!"
  • 📍 现在去右边找e
  • 👶 敲门:"e小朋友好!"
  • 📍 然后找f的孩子i
  • 👶 敲门:"i小朋友好!"
  • ↩️ 回到i的爸爸f:"f叔叔好!"
  • ↩️ 回到f的爸爸c:"c爷爷好!"
  • 🎯 最后终于敲族长a的门:"族长爷爷好!我们见过所有孩子了!"
  • 先给族长送礼物,然后从左到右给孩子们送
  • 确保最重要的长辈先收到礼物
  • 从最旧的书开始整理,到最新的书
  • 自然形成有序排列
  • 从最里面的小房间开始打扫
  • 最后打扫大厅,这样不会重复弄脏
  • 不同的拜访顺序就像不同的社交礼仪
  • 前序遍历尊重长辈,适合重要消息传递
  • 中序遍历讲究顺序,适合整理和搜索
  • 后序遍历关爱晚辈,适合清理和删除操作
  • 前序:我在前,儿孙后
  • 中序:儿在前,我在中,孙在后
  • 后序:儿孙全拜访,最后见老子

(打扫主殿王冠)

🌟 第七章:二叉树王国的智慧

通过这个童话故事,我们学到了:

  1. 节点就像魔法房间​:每个房间存放宝物,并有通向其他房间的门
  2. 建造规则​:左房间编号是当前的2倍,右房间是2倍加1
  3. 三种探险方式​:
    • 勇者喜欢先看眼前(前序)
    • 学者喜欢按顺序查看(中序)
    • 清洁工从最底层开始(后序)

下次当你看到二叉树时,就想象这座魔法城堡,不同的遍历方式就像不同身份的人在城堡中探索!

源码及运行:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
template<typename T>
struct treeNode
{T data;treeNode<T>* left;treeNode<T>* right;treeNode() :data(0), left(NULL), right(NULL) {};treeNode(T d) :data(d), left(NULL), right(NULL) {};};
template<typename T>class Tree
{
private: treeNode<T>* nodes;//所有节点的节点值相当于一个数组分配在堆上treeNode<T>* root;//根节点size_t nodesize;//有多少节点treeNode<T>* creat(T a[], int size, int nodeId, T nullNode);void visit(treeNode<T>* node);//访问单个节点时需要做些事情void preOrder(treeNode<T>* node);void inOrder(treeNode<T>* node);void postOrder(treeNode<T>* node);
public:Tree();Tree(int maxidex);~Tree();treeNode<T>* Gertreenode(int Id);void creatTree(T a[], int size, T nullNode);//传入一个顺序表储存的树从而生成二叉树, T nullNode要定义空树时用这个定义;void preorder();void inorder();void postorder();//因为给外部调用,从根节点开始所以不用传参
};
template<typename T>
Tree<T>::Tree()
{nodes = new treeNode<T>[100000];
}
template<typename T>
Tree<T>::Tree(int maxindex)
{nodesize = maxindex;nodes = new treeNode<T>[nodesize];
}
template<typename T>
Tree<T>::~Tree()
{delete[]nodes;}template<typename T>
treeNode<T>* Tree<T>::Gertreenode(int Id)
{return &nodes[Id];
}
template<typename T>
void Tree<T>:: creatTree(T a[], int size, T nullNode)
{root = creat(a, size, 1, nullNode);
}
template<typename T>
treeNode<T>* Tree<T>:: creat(T a[], int size, int nodeId, T nullNode)
{if (nodeId >= size || a[nodeId] == nullNode){return NULL;}treeNode<T>* nownode = Gertreenode(nodeId);nownode->data = a[nodeId];nownode->left = creat(a, size, 2 * nodeId, nullNode);nownode->right = creat(a, size, 2 * nodeId+1, nullNode);return nownode;
}
template<typename T>
void Tree<T>::visit(treeNode<T>* node)
{cout << node->data;
}
template<typename T>
void Tree<T>::preOrder(treeNode<T>* node)
{if(node){visit(node);preOrder(node->left);preOrder(node->right);}}
template<typename T>
void Tree<T>::inOrder(treeNode<T>* node)
{if (node){inOrder(node->left);visit(node);inOrder(node->right);}
}
template<typename T>
void Tree<T>::postOrder(treeNode<T>* node)
{if (node){postOrder(node->left);postOrder(node->right);visit(node);}
}
template<typename T>
void Tree<T>::preorder()
{preOrder(root);
}
template<typename T>
void Tree<T>::inorder()
{inOrder(root);
}
template<typename T>
void Tree<T>::postorder()
{postOrder(root);
}int main()
{const char nullNpde = '-';char a[15] ={nullNpde,'a','b','c','d',nullNpde,'e','f','g','h',nullNpde,nullNpde,nullNpde,nullNpde,'i'};Tree<char>T(15);T.creatTree(a, 15, nullNpde);T.preorder(); cout << endl;T.inorder(); cout << endl;T.postorder(); cout << endl;return 0;}

http://www.dtcms.com/a/503129.html

相关文章:

  • 厦门手机网站建设wordpress mkv格式
  • spiderdemo题解系列——第2篇:请求头检测挑战(第1题)
  • 数据事件及数据查询——东方财富掘金量化速成学习(python)
  • 数据库做网站wordpress ip地址
  • 上海做网站及推广网站关键词怎么优化
  • 利用汽车雷达测试系统模拟多径效应——论文阅读
  • 【大语言模型】—— 自注意力机制及其变体(交叉注意力、因果注意力、多头注意力)的代码实现
  • TensorFlow2 Python深度学习 - 生成对抗网络(GAN)简介
  • 珠海网站品牌设计公司简介厦门网页
  • 房子网站有哪些在线企业查询系统
  • 临颖网站建设漳州做网站建设
  • Linux oops时进行panic
  • 【Docker】Docker Image(镜像)
  • 重生之我拿捏Linux——《三、shell脚本使用》
  • Altium Designer(AD24)Windows窗口功能总结
  • C++进阶:重载类型转换
  • SKY77645 导致的Rach failure问题
  • C++模版:模板初阶及STL简介
  • 微网站策划方案厦门的网站建设公司
  • 织梦网站404页面模板成都全网推广哪家专业
  • Solidity智能合约存储与数据结构精要
  • 生活化讲解Controller - 餐厅的“前台接待员“
  • AI大事记12:Transformer 架构——重塑 NLP 的革命性技术(下)
  • 微信公众号登录wordpress网站湛江企业网站怎么建设
  • 智慧校园总体解决方案PPT(98页)
  • ComfyUI-DynamiCrafterWrapper:开启ComfyUI动图创作新时代
  • 关于国家授时中心遭受美国国家安全局网络攻击事件的技术分析报告
  • PyGAD使用指南
  • 洛谷 B3841 [GESP202306 二级] 自幂数判断
  • 英诺赛科(02577.HK)