数据结构---树和二叉树

2023-10-28

定义

  1. 有且仅有一个特定的称为根的节点。
  2. 当n>1时,其余节点可分为m(m>0)个互不相交的有限集,每一个集合本身又是一个树,并称为根的子树。
    在这里插入图片描述
    节点1是根节点(root);
    节点5、6、7、8是树的末端,没有“孩子”,被称为叶子节点(leaf)。
    图中的虚线部分,是根节点1的其中一个子树。
    节点4的上一级节点,是节点4的父节点(parent);
    从节点4衍生出来的节点,是节点4的孩子节点(child);
    和节点4同级,由同一个父节点衍生出来的节点,是节点4的兄弟节点(sibling)。
    树的最大层级数,被称为树的高度或深度。显然,上图这个树的高度是4。

二叉树

满二叉树:一个二叉树的所有非叶子节点都存在左右孩子,并且所有叶子节点都在同一层级上,那么这个树就是满二叉树。
在这里插入图片描述

完全二叉树:对一个有n个节点的二叉树,按层级顺序编号,则所有节点的编号为从1到n。如
果这个树所有节点和同样深度的满二叉树的编号为从1到n的节点位置相同,则这个
二叉树为完全二叉树。

在这里插入图片描述
完全二叉树的条件没有满二叉树那么苛刻:
满二叉树要求所有分支都是满的;而完全二叉树只需保证最后一个节点之前的节点都齐全即可

二叉树的物理结构

链式存储

在这里插入图片描述
二叉树的每一个节点包含3部分。

  1. 存储数据的data变量
  2. 指向左孩子的left指针
  3. 指向右孩子的right指针

数组

在这里插入图片描述

假设一个父节点的下标是parent,那么它的左孩子节点下标就是2×parent +1;右孩子节点下标就是2×parent + 2

反之

假设一个左孩子节点的下标是leftChild,那么它的父节点下标就是(leftChild-1)/ 2。

存在的问题:显然,对于一个稀疏的二叉树来说,用数组表示法是非常浪费空间的。

二叉堆:一种特殊的完全二叉树,就是用数组来存储的。

二叉树应用

查找

二叉查找树(二叉排序树)
如果左子树不为空,则左子树上所有节点的值均小于根节点的值
如果右子树不为空,则右子树上所有节点的值均大于根节点的值
左、右子树也都是二叉查找树
在这里插入图片描述
对于一个节点分布相对均衡的二叉查找树来说,如果节点总数是n,那么搜索节点的时间复杂度就是O(logn),和树的深度是一样的。
这种依靠比较大小来逐步查找的方式,和二分查找算法非常相似。

维持相对顺序

二叉查找树要求左子树小于父节点,右子树大于父节点,正是这样保证了二叉树的有序性。
一个问题:
在这里插入图片描述
查询节点的时间复杂度也退化成了O(n)。

解决:就涉及二叉树的自平衡了。二叉树自平衡的方式有多种,如红黑树、AVL树、树堆等

二叉树的遍历

二叉树,是典型的非线性数据结构,遍历时需要把非线性关联的节点转化成一个线性的序列,以不同的方式来遍历,遍历出的序列顺序也不同。

从节点之间位置关系的角度

  1. 前序遍历
  2. 中序遍历
  3. 后序遍历
  4. 层序遍历

从更宏观的角度

  1. 深度优先遍历(前序遍历、中序遍历、后序遍历)。
  2. 广度优先遍历(层序遍历)。

深度优先遍历

前序遍历

输出顺序是根节点、左子树、右子树
在这里插入图片描述

中序遍历

输出顺序是左子树、根节点、右子树。
在这里插入图片描述

后序遍历

输出顺序是左子树、右子树、根节点。
在这里插入图片描述

二叉树的这3种遍历方式,用递归的思路可以非常简单地实现出来

package dataStructure.binaryTree;

import java.util.Arrays;
import java.util.LinkedList;

public class bineryTree {

    //静态内部类
    //二叉树节点
    private static class TreeNode{
        int data;
        TreeNode leftChild;
        TreeNode rightChild;

        public TreeNode(int data) {
            this.data = data;
        }
    }

    /**
     * 前序遍历的链表节点的顺序.来创建二叉树
     * @param inputList
     * @return
     */
    public static TreeNode precreatBinaryTree(LinkedList<Integer> inputList){
        TreeNode node = null;
        if(inputList==null||inputList.isEmpty()){
            return null;
        }
        Integer data = inputList.removeFirst();
        if(data!=null){
            node = new TreeNode(data);
            node.leftChild=precreatBinaryTree(inputList);
            node.rightChild = precreatBinaryTree(inputList);
        }
        //将根节点返回(用于遍历,不返回根节点,这个树怎么找。。。。。)
        return node;
    }
    /**
     * 前序遍历
     * @param node
     */
    public static void preOrderTraveral(TreeNode node){
        if(node==null){
            return;
        }
        System.out.println(node.data);
        preOrderTraveral(node.leftChild);
        preOrderTraveral(node.rightChild);
    }

    /**
     * 中序遍历
     * @param node
     */
    public static void inOrderTraveral(TreeNode node){
        if (node==null){
            return;
        }
        inOrderTraveral(node.leftChild);
        System.out.println(node.data);
        inOrderTraveral(node.rightChild);
    }

    /**
     * 后序遍历
     * @param node
     */
    public static void postOrderTraveral(TreeNode node){
        if (node==null){
            return;
        }
        postOrderTraveral(node.leftChild);
        postOrderTraveral(node.rightChild);
        System.out.println(node.data);
    }

    public static void main(String[] args) {
        //前序创建二叉树
        LinkedList<Integer> inputList = new LinkedList<Integer>(Arrays.asList(new Integer[]{3,2,9,null,null,10,null,null,8,null,4}));
        TreeNode treeNode = precreatBinaryTree(inputList);
        System.out.println("前序遍历");
        preOrderTraveral(treeNode);
        System.out.println("中序遍历");
        inOrderTraveral(treeNode);
        System.out.println("后序遍历");
        postOrderTraveral(treeNode);




    }
}

二叉树的构建方法有很多,这里把一个线性的链表转化成非线性的二叉树,链表节点的顺序恰恰是二叉树前序遍历的顺序。链表中的空值,代表二叉树节点的左孩子或右孩子为空的情况。
在这里插入图片描述

二叉树广度优先遍历

层序遍历

在这里插入图片描述
每个节点左侧的序号代表该节点的输出顺序。
借助队列完成二叉树层序遍历

 //队列实现
    public static void levelOrderTraversal(TreeNode root){
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        //向队列中插入元素,如果操作成功返回true,反之返回false。
        queue.offer(root);
        while (!queue.isEmpty()){
            //poll()返回队首元素的同时删除队首元素
            TreeNode node = queue.poll();
            System.out.println(node.data);
            if (node.leftChild!=null){
                queue.offer(node.leftChild);
            }
            if(node.rightChild!=null){
                queue.offer(node.rightChild);
            }
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构---树和二叉树 的相关文章

随机推荐

  • html表格里面怎么合并单元格的快捷键,合并单元格快捷键ctrl加什么?

    01 先选择要合并的单元格 按CTRL 1键 再用 及 方向键移动到第二个选项卡 再按ALT M键 再按确定 完成 Excel是Microsoft为使用Windows和AppleMacintosh操作系统的电脑编写的一款电子表格软件 Wor
  • Kali-linux安装之后的简单设置

    1 更新软件源 修改sources list文件 leafpad etc apt sources list 然后选择添加以下适合自己较快的源 可自由选择 不一定要全部 官方源 deb http http kali org kali kali
  • C++ map的常用用法(超详细)(*^ー^)人(^ー^*)

    C 中的map翻译为映射 不是地图 也是常用的STL容器 它在算法竞赛中应用十分广泛 因为map可以将任何基本类型 包括STL容器 映射到任何基本类型 包括STL容器 十分灵活 因此我们很有必要来熟练map的常用用法 目录 1 map的定义
  • 虚拟实验服务器,MED-V动手实验一:服务器部署

    IT168 专稿 微软在2009年4月份发布的MDOP2009中提供了MED V的正式版本 MED V是Microsoft Enterprise Desktop Virtualization的缩写 顾名思义 MED V为企业提供了桌面虚拟化
  • PHY 驱动目录树构建

    在看Linux网络PHY设备驱动的时候一直有个问题萦绕心头 久久挥之不去 辗转反侧 难以入眠 不是因为看了不 懂 而是因为大体的流程都不明白 主要体现在以下几点 1 在注册PHY设备时 驱动所需要的总线是什么时候准备好的 2 总线 设备 驱
  • CTF MISC图片隐写简单题学习思路总结(持续更新)

    系列文章目录 第一篇文章 CTF Crypto简单题学习思路总结 持续更新 文章目录 系列文章目录 前言 一 JPG类隐写 1 1 JPG文件末尾添加字符串 1 2 JPG文件中添加字符串 1 3 图片文件分离 1 4 JSteg JPHi
  • Filesystem Hierarchy Stardard(FHS)规定Linux应放置文件内容

    第一部分 FHS要求必须要存在的目录 第二部分 FHS建议可以存在的目录 第三部分 其他重要 来源 鸟哥的Linux私房菜 基础篇 第四版
  • Safari的html5 localStorage错误:“ QUOTA_EXCEEDED_ERR:DOM异常22:试图向存储中添加超出配额的内容”...

    如何解决Safari的html5 localStorage错误 QUOTA EXCEEDED ERR DOM异常22 试图向存储中添加超出配额的内容 显然 这是设计使然 当Safari OS X或iOS 处于私有浏览模式时 它似乎local
  • Spring解决循环依赖的思路与代码实现

    Java基基 2023 09 08 11 55 发表于上海 这是一个或许对你有用的社群 一对一交流 面试小册 简历优化 求职解惑 欢迎加入 芋道快速开发平台 知识星球 下面是星球提供的部分资料 项目实战 视频 从书中学 往事中 练 互联网高
  • 程序员面试、算法研究、编程艺术、红黑树、机器学习5大系列集锦

    程序员面试 算法研究 编程艺术 红黑树 机器学习5大经典原创系列集锦与总结 七月在线 https www julyedu com 面试 算法 机器学习在线课程 作者 July 结构之法算法之道blog之博主 时间 2010年10月 2018
  • linux下phpMyAdmin 出现 “缺少 mysqli 扩展,请检查 PHP 配置。”

    问题一 原因 mysqli这个扩展没有安装 或者你没有在php ini里面加入extension mysqli d 解决方案 yum install php mysql 然后重启apache 或者 编辑php ini 在最后加入 exten
  • 多元回归分析

    多元回归分析 MLR多元线性回归多输入单输出预测 Matlab完整程序 目录 多元回归分析 MLR多元线性回归多输入单输出预测 Matlab完整程序 预测结果 评价指标 基本介绍 程序设计 参考资料 预测结果 评价指标 训练集数据的R2为
  • 学习笔记十九:Pod常见的状态和重启策略

    Pod常见的状态和重启策略 常见的pod状态 第一阶段 第二阶段 扩展 pod重启策略 测试Always重启策略 正常停止容器内的tomcat服务 非正常停止容器里的tomcat服务 测试never重启策略 正常停止容器里的tomcat服务
  • 随机图片API

    文章目录 创建自己的图库 创建index php和img txt img txt写入图片链接 一行一个图片链接 可直接调用接口 二次元随机图 API 随机二次元接口源码 双版本 直接调用API 创建自己的图库 创建index php和img
  • java引入包_java如何导入包

    展开全部 1 首先在项目下创建一个新的文件夹 用来保存jar包 在项目名上点击鼠标62616964757a686964616fe4b893e5b19e31333431336665右键 按顺序点击 New Floder 打开新建文件夹的窗口
  • (Java)leetcode-124 Binary Tree Maximum Path Sum(二叉树中的最大路径和)

    更多LeetCode题解 可移步我的解题记录 持续更新中 题目描述 给定一个非空二叉树 返回其最大路径和 本题中 路径被定义为一条从树中任意节点出发 达到任意节点的序列 该路径至少包含一个节点 且不一定经过根节点 示例 1 输入 1 2 3
  • mysql行锁sql语句怎么写_mysql的锁

    在MySQL中 不同的存储引擎采用的不同的锁机制 如MyISAM和MEMORY存储引擎采用表级锁 InnoDB存储引擎既支持行级锁 也支持表级锁 MySQL中使用表锁的语句如下 lock table table name read 共享读锁
  • RandomAccessFile的常见用法

    1 RandomAccessFile的简介 1 1为什么要用到RandomAccessFile 我们平常创建流对象关联文件 开始读文件或者写文件都是从头开始的 不能从中间开始 如果是开多线程下载一个文件我们之前学过的FileWriter或者
  • Web服务器群集:Nginx之Rewrite重写

    目录 一 理论 1 Nginx正则表达式 2 location匹配 3 rewrite重写 4 if指令与全局变量 二 实验 1 基于域名的跳转 2 基于客户端 IP访问跳转 3 基于旧域名跳转到新域名后面加目录 4 基于参数匹配的跳转 5
  • 数据结构---树和二叉树

    树和二叉树 定义 二叉树 二叉树的物理结构 链式存储 数组 二叉树应用 查找 维持相对顺序 二叉树的遍历 深度优先遍历 前序遍历 中序遍历 后序遍历 二叉树广度优先遍历 层序遍历 定义 有且仅有一个特定的称为根的节点 当n gt 1时 其余