数据结构之树

数据结构之树

  1. 定义

    n(大于等于0)个结点形成的层次结构,若n=0,则为空树;n=1,则为单结点树;当n>1时,存在一个结点作为树的根,其余结点形成根的子树(子树也是树~);两个结点之间的连线表示结点间的父子关系;

  2. 基本概念
    • 没有父结点的结点称为根节点;
    • 结点的度:该结点的子树个数;
    • 度为0的结点称为叶子结点;也叫终端结点;非叶子结点称为分支结点;
    • 树的元数:一棵树中所允许的最大结点度数称为该树的元数;
    • 儿子结点:结点的子树之根结点称为该结点的儿子结点;
    • 父亲结点:如果s结点是f结点的儿子结点,那么f则称为s的父结点;父结点也成称为前驱结点,子节点也称为后继结点;树中每个结点有0个或1个前驱结点;由于根结点没有前驱结点,所以n个结点的树有n-1跳边;
    • 兄弟结点:有相同父亲结点的结点互为兄弟结点;
    • 子孙结点、真子孙结点:一个结点的子孙结点包括它本身和所有它的子树中的结点;真子孙结点为除去它自己本身的其他子孙结点;
    • 路径:为一个结点序列,该序列中任何相邻的两个结点之间为父子关系,前者是后者的父亲结点;路径中边的数量称为路径长度;这里的路径指的是没有重复结点的路径;
    • 结点的层数:记根结点的层数为1,第 n 层结点的儿子的层数为n+1;
    • 结点的高度:记叶子结点的高度为1,则分支结点的高度为所有子树高度中的最大值+1;特别的树的高度为根结点的高度;
    • 有序树、无序树;位置树;如果要求一棵树中各结点的子结点的出现需要按照一定的顺序,则称该树为有序树;否则为无序树;位置树是结点位置确定的树,即使某个结点为空,其他结点也不能占据其位置;
    • 森林:n(大于等于0)棵树构成一个森林;
  3. 基本性质
    1. 二叉树的概念及基本性质

      二叉树是一棵二元树,也是一棵位置树。结点的两个子树分别称为左子树和右子树;左右子树的根结点分别称为左右儿子;

      基本性质:(二叉树有很多好的性质,在设计算法时应当充分利用)

      • 在非空二叉树中,第n层上的结点个数x满足:x小于等于2^(n-1);(n大于等于1,当n=1时即为根结点);

      • 高为K的二叉树中,结点总数M满足M小于等于2^K-1;(K大于等于0,当K==0时为空树);

      • M个结点的二叉树的高h满足:h大于等于以2为底M的对数向下取整后+1;

      注意,按照上面的等式,h大于等于以2为底(M+1)的对数(记为H),由于h应为整数,所以要先对H进行向下取整,如果H本身为整数,那么,h>=floor(H);如果H本身为小数,那么h>=floor(H)+1;即引入floor操作并没有办法得到一个统一的表达式;问题出在h是通过大于等于符号和H关联的,假设h严格大于H,那么即使H本身为整数,考虑到h为整数,h>=H+1=floor(H)+1;如果H为小数,那么h>=floor(H)+1也是可以的;所以就需要放缩啦;放缩的结果即为结论;

      满二叉树与完全二叉树

      • 满二叉树:第K(K大于等于1)层上共有2^(K-1)个结点的二叉树;此时该树的高度为h,则结点总数为2^h-1;
      • 完全二叉树:叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置;

      完全二叉树的性质:

      • n个结点的完全二叉树,其树高h=以2为底n的对数向下取整后+1;
      • 编号为J的结点,其父亲、左子结点、右子节点的编号满足:若J=1,则无父结点,否则J/2为其父结点(注意与J/2.0的区别);其其左子节点编号为2J,如果存在;右子节点编号为2J+1,如果存在;
  4. 相关算法
    1. 树的存储方法

      • 多重链接法:其结点核心构造为“值域+N个子结点域”;每个子结点指针指向一棵子树;特点是简单易懂,符合树的定义,但是对于叶子结点来说,其指针域为空,造成不小的浪费,实际利用率只有N分之一;N较小的时候尚可接受;
      • 左儿子右兄弟链接法:其核心理念为”在父结点的角度看来,儿子的兄弟仍为父结点的儿子;站在自己的角度来看,兄弟的兄弟仍为自己的兄弟”;所以每个结点只要分别保留一个指向儿子结点和兄弟结点的指针即可保留所有关系;
      • 父亲链接法:每个结点都存储一个指向自己父亲结点的指针;这样便于从下层往上层查找;实际上使用辅助数组来A记录这种关系是最好的,比如A[1]=2;表示编号为1的结点,其父节点编号为2;

      特别的,完全二叉树中由于特殊性质,也可以使用数组来存储;

    2. 树的遍历方法

      所谓树的遍历,其实质是结合树的存储方式并按照某种顺序访问树中所有结点,访问的过程可以将层次结构的树变为线性结构;

      常见的树的遍历方法大概分为两种:广度优先法和深度优先法;(这两种方法是遍历连通图的两种方法,在图的相关总结中,会发现,树也是一种连通图~)

      广度优先遍历:其核心为“按层遍历”,首先访问第一层所有结点,然后访问第二层。。。。

      过程如下:从某棵树的根结点出发,首先访问该结点的所有子结点,并且按照访问子结点的顺序将子结点入队列,形成新的出发点的候选队列;当所有子结点入队列后,将候选队列中的队头元素作为新的出发点,重复该过程,直到候选队列为空,遍历就完毕啦;

      深度优先遍历:其核心为只有深度优先遍历完一棵树后才进行另一棵树(通常为兄弟树)的遍历;遍历完成的标志是访问到该树中所有的结点;

      过程如下:从某棵树的根结点开始,首先访问根结点,然后将其第一个子结点作为新的根结点执行深度优先遍历;当第一棵子树完毕后,再对第二棵子树执行,直到所有子树都执行完毕后这棵树的深度优先遍历就结束啦;

      对于二叉树,遍历又可以分为先序遍历、中序遍历以及后序遍历,该部分内容在二叉树专题中详细记录;

    3. 普通树与二叉树的相互转化

      普通树 to 二叉树:

      对于一棵普通树,根结点保持不变,断开根结点同其子结点的连接,此时根结点的子树便形成森林;然后将该森林转换为一棵二叉树作为根结点的左子树,由于根结点没有兄弟结点所以根结点便没有右子树;

      二叉树 to 普通树:

      二叉树BT的根结点作为普通树PT的根结点;将BT根结点的左子树转换为森林,作为PT的子树;

    4. 森林与二叉树的相互转化

      森林 to 二叉树:采用“左儿子右兄弟”的规则,添加一个虚拟根结点,原来森林中各个树的根结点便互为兄弟结点啦,然后把森林中最左边的子树的根结点作为二叉树的根结点;将根结点的子树(也是森林)转换为二叉树作为根结点的左子树;森林中其它的树转换为二叉树作为根结点的右子树;

      二叉树 to 森林:

      二叉树BT的根结点作为森林F中第一棵树的根结点;将BT根结点的右子树转换为森林,作为F中的一部分;将BT根结点的左子树转换为森林,作为第一棵树的子树;转换完毕;

      其实,一棵树也是一个森林,故只需实现森林同二叉树的转换算法,即可实现树与二叉树的相互转换;

    本文源码github地址(这是自己使用Java语言(部分细节参考了Java集合类源码)实现的一套数据结构API,包括链表,栈、队列、树、图等内容,为算法学习提供基础,完善ing~)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值