数据结构-树

本文详细介绍了树与二叉树的相关概念,包括特殊类型的二叉树(满二叉树、完全二叉树等)、存储方式(链式存储、线索二叉树)、遍历方法以及二叉排序树、平衡二叉树(AVL树)和哈夫曼树(最优二叉树)的定义、实现和应用。特别地,文章提供了Java实现的示例,帮助读者更好地理解和运用这些数据结构。
摘要由CSDN通过智能技术生成

一、树

度 :
 - 结点度:该节点含有的子节点个数
 - 树的度:取该树中结点度最大的那个值

分支结点:度 > 0 的结点
叶子结点:度 > 0 的结点

森林:多棵互不相交的树的集合

性质:

  • 树中结点的个数 = 各结点的度之和 + 1
  • 高度为h的m叉树的结点个数(Max) = (mh - 1)/(m - 1)

二、二叉树

二叉树的左右结点严格区分,即使只有一个结点度为1也要分清楚

二叉树与度为2的有序树的差别:
- 二叉树可为空,后者则至少有3个结点
- 二叉树的孩子节点始终有左右之分,而后者则是相对的

二叉树的性质:
- n0 = n2+1(度为0的结点个数 = 度为2的结点 + 1)
- 编号为i的结点所在的层 = log2i + 1 向下取整

1.特殊二叉树(满二叉树、完全二叉树、二叉排序树、平衡二叉树、)

满二叉树性质:

  • 一棵高为h的满二叉树的结点个数 = 2h-1
  • 编号为i的结点=>双亲结点 = i / 2 ; 左孩子结点 = 2i 、右孩子结点= 2i+1;

完全二叉树:

定义:
二叉树的所有编号都与其对应的满二叉树完全一致,那么它就是完全二叉树

例:
在这里插入图片描述

性质:
- 一棵有n个结点的完全二叉树=> 编号 i = n / 2 的结点是最后一个分支结点(该编号以前全是分支结点,以后全是叶子结点)
- 若度为1的结点存在,那么只能有一个,且是左孩子节点,该孩子结点编号为n

二叉排序树:

定义:任意一个结点的左子树小于它、右子树大于它

例:
在这里插入图片描述


平衡二叉树:

定义:任意一个结点的左子树与右子树的深度差小于1,建立在二叉排序树之上的。
目的是为了防止二叉排序树层级增加过快导致检索速度下降,而引入平衡二叉树

例:在这里插入图片描述

2.存储方式

1.顺序存储(使用数组):0号插结点数,之后直接根据编号一一对应插入数组,结点直接的关系通过双亲编号i = 孩子结点的两倍来计算
(适用于完全(满)二叉树,其他二叉树有空间利用浪费)

2.二叉树链式孩子存储 :
存储结构:
在这里插入图片描述
存储方式:
在这里插入图片描述


链式左孩子右兄弟存储 :
原理同上,方便将树转化成二叉树

  • 左指针指向第一个孩子
  • 右指针指向下一个兄弟

3.遍历方式(left > right)

中序遍历 + 任意前后序列 = 确定唯一序列
(前 + 后) 不可×

在这里插入图片描述 在这里插入图片描述


在这里插入图片描述在这里插入图片描述


在这里插入图片描述在这里插入图片描述

4.线索二叉树(java)

在链式存储的条件下合理利用空指针的一种二叉树

二叉树的线索化(根据某种遍历方式):

  • 如果该结点的左子树为空,则将该节点左指针指向前驱结点;
  • 如果该节点的右子树为空。则将该结点右指针指向后驱结点;

二叉树中序线索化代码实现原理:
对当前结点线索化时:

  • 判断当前左孩子是否为空,若为空,则左指针 = perNode
  • 判断preNode的右孩子是否为空,若为空,则右指针 = this.node

二叉树中序线索化代码实现

 /**
     * 中序线索化二叉树
     * @param node  当前节点
     * @param perNode 当前线索化结点之前的那个结点(重点线索化!未进行线索化之前一直都是null,所以中序遍历的一个节点的前驱线索为null)
     */
     Node perNode = null;
    void inThreadOrder(Node node) {
   
        if(node == null) {
   
            return;
        }
 
        //处理左子树
        inThreadOrder(node.left);
 
        //如果当前结点的左孩子为空,将左指针指向前驱节点
        if(node.left == null) {
   
            node.left = preNode;
            node.leftFlag= true;
        }
 
        //非起点且当前线索化节点的前一个结点的右孩子为空,将右指针指向当前结点
        if(preNode != null && preNode.right == null) {
   
            preNode.right = node;
            preNode.rightFlag = true;
        }
		//中序遍历下个结点之前,将当前结点设置为preNode
        preNode = node;
 
        //处理右子树
        inThreadOrder(node.right);
    }

中序遍历线索二叉树,按照后继方式遍历(思路:找到最左子节点开始):

/**
     * 中序遍历线索二叉树,按照后继方式遍历(思路:分两步:1、找到最左子节点开始,2、从起点开始遍历)
     * @param node
     */
    void inThreadList(Node node) {
   
        //1、找中序遍历方式开始的节点
        while(node != null && !node.isLeftThread) {
   
            node = node.left;
        }
 		
 		//2、从起点开始遍历,
        while(node != null) {
   
            System.out.print(node.data + ", ");
 
            //如果右指针是线索,那么下一个结点直接指向线索
            if
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值