我的第一棵树--家谱

本文介绍了构建家谱的过程,重点讨论了树数据结构的理解,包括结点的定义、动态内存分配以及如何通过层序遍历来建立家谱。文章详细阐述了建树、遍历、插入、删除、查询等操作,并强调了在进行这些操作时正确处理内存的重要性,特别是涉及动态内存申请和释放的细节。
摘要由CSDN通过智能技术生成


家谱构建第一步,就是要理解内存。树实际上就是一个多叉链表,一个数据域,几个指向跟自己有关系的元素的指针域,就
构成了树的结点。而要建立链表,把一个一个结点赋值,就要传指向它们的指针BiTree了,这样才能修改结点的值。因为通过
子函数来建立一棵树,每开辟一个新节点,就malloc动态申请一块内存区域,这块区域在堆区,子函数结束时不会销毁。
但在主函数里定义一棵树,一定要把树的地址传到子函数里,这样才能修改即给树添加结点建立一棵树,在子函数里给树的
根节点(*T)动态申请一块内存,把输入的值赋过去,就构造好了根节点。而之后的结点,就通过不断地malloc构造新节点,
然后利用结点的各种指针域,赋值,把它们连接起来。连接的过程用到的是在子函数里定义的临时BiTree指针变量,只是通过
它们实现链接。而我们刚开始已经抓住了“绳子的头”(*T),就可以把树直接拿来操作啦。


理解了子函数的参数类型,就剩下思路了。刚开始我没有父亲节点,几个子函数勉强写出了,可是到删除某人的时候实在做不
下去了,后来加上父亲节点发现再缕思路的时候真是得心应手。历时三天半,我的第一棵树终于告一段落啦。


这里关键是建树和遍历,完成这两部分,基本就算写完了。建树,家谱要用层序建树,这里用到队列,利用它先进先出的排队
性质,从根节点开始,每一层从左到右遍历着赋值,先根节点入队列,用一个BiTree类型的变量接收根节点出队列,循环从此
展开,手动判断有无孩子,若有,连到lchild域,判断有没有孩子也是一个循环,设定一个标志,若一直有,则循环把新孩子
尾插到rsib兄弟结点,同时当把新结点连到旧结点的时候,新节点入队列,直到输入不再有孩子。这时候第一个入队列的节点
即左孩子出队列,重复以上先判断有无左孩子,把孩子们链接到上一个对应结点并入队列的过程,队列实现了每一层从左到右
的顺序插入,遍历,实现了层序。


然后,插入删除增加查询,查询时可以升级到查出一个人连带他的祖宗们兄弟们儿子们,还有问有没有孩子的时候,记得把当前
结点的名字打印出来,更只能人性化一点。


查询,在遍历的基础上,找到这个人,若是祖先,只打印儿子们;若不是,利用父亲指针找到父亲,循环找到祖宗,再找兄弟,
两种情况,若是父亲的左孩子,依次打印右兄弟,若不是左孩子,则从左孩子开始依次打印父亲的孩子,通过判断跳过本身。
再找儿子,依次遍历打印。


增加儿子,在遍历的基础上,找到要增加儿子的父亲节点,若没有左孩子,。。。若有左孩子,尾插。


增加兄弟,在遍历的基础上,找到要增加兄弟的节点,新节点尾插到最后那个兄弟的右兄弟域。


删除儿子,在遍历的基础上,找到要删除的儿子指针,若本身是父亲左孩子,,,,若不是,,,,。


删除兄弟,在遍历的基础上,找到要删除的兄弟结点,若是父亲左孩子,,,,若不是,,,,。


删除某个人,在遍历的基础上,找到要删除的结点,若是祖宗,,,若是父亲左孩子,,,若不是,,,。


注意删除某个人要把他的子子孙孙都删掉。


删除添加操作都要改变一棵树,所以需要传树的地址,二级指针。把树的根节点地址传进去,中间的临时变量不用设为指针类型。


free()括号里是指针变量,销毁指向部分的内存。

释放一棵子树的时候,要提前把它的右兄弟置为NULL,否则无法通过后序遍历释放节点空间。



主函数:
#include<stdio.h>
#include"B
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值