【数据结构与算法】二叉树的以及二叉排序树的实现

news2024/9/25 17:22:38

目录

通过数组实现二叉树

通过链表实现二叉树

排序二叉树的实现


通过数组实现二叉树

该实现方式只能用于完全二叉树,因为如果是普通二叉数的话,数组中会出现空隙,会导致空间的利用率会降低。

实现思路:

        因为假设一个父节点的下标为parentIndex,那么他的左子节点的下标就为2parentIndex,他的右子节点的下标就为2parentIndex+1。

        所以想要获取一个左子节点时只需将她父节点的下标通过<<1即可(相当于* 2)获得左子节点的下标,获取右子节点时与之相同,不过在<<1的同时在+1。

        而将一个数组直接转换为二叉树只需将数组下标向右移一位即可,下标从1开始。

/**
 * @author CC
 * @version 1.0
 * @since2023/10/7
 * 使用数组实现二叉树
 */
public class BinaryToArrayTree<E> {
    private Object[] elementData = null;

    /**
     * 有参构造 直接将一个数组变为二叉树
     * @param elements
     */
    public BinaryToArrayTree(E[] elements) {
        elementData = new Object[elements.length + 1];

        for (int i = 0, index = 1; i < elements.length; i++, index++) {
            elementData[index] = elements[i];
        }
    }

    /**
     * 获取该下标的值
     * @param index
     * @return
     */
    public E get(int index){
        return (E) elementData[index];
    }

    /**
     * 获取该下标的左子节点的值
     * @param index
     * @return
     * @throws Exception
     */
    public E left(int index) throws Exception {
        if ((index<<1)>=elementData.length){
            throw new Exception("左孩子节点不存在!");
        }
        return (E) elementData[index<<1];
    }

    /**
     * 获取该下标的右子节点的值
     * @param index
     * @return
     * @throws Exception
     */
    public E right(int index) throws Exception {
        if (((index<<1)+1)>=elementData.length){
            throw new Exception("右孩子节点不存在!");
        }
        return (E) elementData[(index<<1)+1];
    }
 }

测试

public class BATest {
    public static void main(String[] args) throws Exception {
        String[] array ={"A","B","C","D","E","F","G","H"};
        BinaryToArrayTree<String> binaryTree =new BinaryToArrayTree<>(array);
        System.out.println("下标为1的节点值"+binaryTree.get(1));
        System.out.println("下标为1的左子节点值"+binaryTree.left(1));
        System.out.println("下标为1的右子节点值"+binaryTree.right(1));
    }
}

测试结果

通过链表实现二叉树

/**
 * @author CC
 * @version 1.0
 * @since2023/10/7
 * 使用链表实现二叉树
 */
public class BinaryToListTree<E> {
    TreeNode<E> root;//根节点

    public BinaryToListTree(E val) {
        root = new TreeNode<E>(val);
    }

    /**
     * 存入左节点
     * @param parent 父节点
     * @param val 左节点的值
     * @return
     */
    public TreeNode<E> left(TreeNode<E> parent, E val) {
        TreeNode<E> newNode = new TreeNode<>(val);
        parent.left = newNode;
        return newNode;
    }

    /**
     * 存入右节点
     * @param parent 父节点
     * @param val 右节点的值
     * @return
     */
    public TreeNode<E> right(TreeNode<E> parent, E val) {
        TreeNode<E> newNode = new TreeNode<>(val);
        parent.right = newNode;
        return newNode;
    }

    /**
     * 先序遍历
     * @param root 根节点
     */
    public void preOrder(TreeNode root){
        if (root==null){
            return;
        }
        System.out.print(root.data);
        preOrder(root.left);
        preOrder(root.right);
    }

    /**
     * 中序遍历
     * @param root 根节点
     */
    public void inOrder(TreeNode root){
        if (root==null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.data);
        inOrder(root.right);
    }

    /**
     * 后序遍历
     * @param root 根节点
     */
    public void postOrder(TreeNode root){
        if (root==null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.data);
    }


    /**
     * 层序遍历
     * @param root 根节点
     */
    public void levelOrder(TreeNode root){
        if (root ==null){
            return;
        }
        Queue<TreeNode> queue =new LinkedList<>();
        queue.offer(root);
        while (true){
            TreeNode cur = queue.poll();
            if (cur==null){
                return;
            }

            System.out.print(cur.data);
            if (cur.left!=null){
                queue.offer(cur.left);
            }
            if (cur.right!=null){
                queue.offer(cur.right);
            }
        }
    }


    /**
     * 节点类
     * @param <E>
     */
    public static class TreeNode<E> {
        E data;//数据
        TreeNode<E> left;//左节点
        TreeNode<E> right;//右节点

        public TreeNode() {
        }

        public TreeNode(E val) {
            this.data = val;
        }
    }
}

测试

public class BLTest {
    public static void main(String[] args) {
        BinaryToListTree<String> tree =new BinaryToListTree<>("A");

        //将B C 分别存入A 的左右节点
        BinaryToListTree.TreeNode<String> b= tree.left(tree.root, "B");
        BinaryToListTree.TreeNode<String> c= tree.right(tree.root, "C");

        //将D E 分别存入B 的左右节点
        BinaryToListTree.TreeNode<String> d= tree.left(b, "D");
        BinaryToListTree.TreeNode<String> e= tree.right(b, "E");

        //将F G 分别存入C 的左右节点
        BinaryToListTree.TreeNode<String> f= tree.left(c, "F");
        BinaryToListTree.TreeNode<String> g= tree.right(c, "G");

        System.out.println("根节点:"+tree.root.data);
        System.out.println("根节点的左子节点:"+tree.root.left.data);
        System.out.println("根节点的右子节点:"+tree.root.right.data);
        System.out.println("根节点的左子节点的左子节点:"+tree.root.left.left.data);
        System.out.println("根节点的左子节点的右子节点:"+tree.root.left.right.data);
        System.out.println("根节点的右子节点的左子节点:"+tree.root.right.left.data);
        System.out.println("根节点的右子节点的右子节点:"+tree.root.right.right.data);


        System.out.print("前序遍历:");
        tree.preOrder(tree.root);
        System.out.println();

        System.out.print("中序遍历:");
        tree.inOrder(tree.root);
        System.out.println();

        System.out.print("后序遍历:");
        tree.postOrder(tree.root);
        System.out.println();

        System.out.print("层序遍历:");
        tree.levelOrder(tree.root);

    }

}

测试结果

排序二叉树的实现

实现思路:

二叉排序数他的实现思路是父节点的左子节点一定小于父节点,而父节点的右子节点一定大于父节点,所以排序二叉树的中序遍历就是就是该二叉树节点从小到大的排序。他的最大值就是根节点的最右子节点,而最小值就是根节点的最左子节点。

/**
 * 二叉排序树
 * @author CC
 * @version 1.0
 * @since2023/10/8
 */
public class BinarySortTree {

    TreeNode root;//根节点

    /**
     * 初始化方法
     * @param arr
     */
    public void init(int[] arr){
        for (int i : arr) {
            insert(new TreeNode(i));
        }
    }

    /**
     * 中序遍历
     * @param node
     */
    public void inOrder(TreeNode node){
        if (node==null){
            return;
        }
        inOrder(node.left);
        System.out.print(node.data+" ");
        inOrder(node.right);
    }


    /**
     * 插入节点
     * @param newNode
     */
    public void insert(TreeNode newNode){
        TreeNode currentNode =this.root;//查找过程中的当前节点
        TreeNode parent =null;//插入节点的父节点

        //查找新节点的插入位置
        while (currentNode !=null){
            parent =currentNode;
            if (newNode.data<currentNode.data){
                currentNode =currentNode.left;
            }else {
                currentNode = currentNode.right;
            }
        }

        //查找到的最终节点作为新节点的父节点
        newNode.parent =parent;

        //如果该该树为空 没有父节点
        if (parent==null){
            this.root =newNode;
        }else {
            if (newNode.data<parent.data){
                parent.left =newNode;
            }else {
                parent.right=newNode;
            }
        }
    }

    /**
     * 通过节点值和节点查找
     * @param currentNode
     * @param data
     * @return
     */
    private TreeNode search(TreeNode currentNode,Integer data){
        if (currentNode==null){
            return null;
        }
        if (data<currentNode.data){
            return search(currentNode.left,data);
        }else if (data>currentNode.data){
            return search(currentNode.right,data);
        }else {
            return currentNode;
        }
    }

    /**
     * 通过节点值查找查找 默认从根节点开始查找
     * @param data
     * @return
     */
    public TreeNode search(Integer data){
        TreeNode resultNode =search(this.root,data);
        return resultNode;
    }


    /**
     * 查找最大值
     * @param currentNode
     * @return
     */
    public TreeNode max(TreeNode currentNode){
        if (currentNode==null){
            return null;
        }
        TreeNode parent =null;

        while (currentNode!=null){
            parent =currentNode;
            currentNode=currentNode.right;
        }
        return parent;
    }


    /**
     * 查找最小值
     * @param currentNode
     * @return
     */
    public TreeNode min(TreeNode currentNode){
        if (currentNode ==null){
            return null;
        }
        TreeNode parent =null;

        while (currentNode!=null){
            parent=currentNode;
            currentNode =currentNode.left;
        }
        return parent;
    }

    /**
     * 节点类
     */
    static class TreeNode{
        Integer data; //节点数据
        TreeNode left; //左子节点
        TreeNode right; //右子节点
        TreeNode parent; //父节点

        public TreeNode(){
        }

        public TreeNode(Integer val){
            this.data =val;
        }
    }
}

测试

public class BSTest {
    public static void main(String[] args) {
        BinarySortTree bst =new BinarySortTree();
        bst.init(new int[] {2,8,6,9,31,3,5,21,7,14});

        System.out.print("中序遍历:");
        bst.inOrder(bst.root);
        System.out.println();

        BinarySortTree.TreeNode node = bst.search(2);
        System.out.println("查找2:"+node.data);

        System.out.println("最大值:"+bst.max(bst.root).data);
        System.out.println("最小值:"+bst.min(bst.root).data);
    }
}

测试结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1074357.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电商数据的采集标准

品牌在做控价或者数据分析时&#xff0c;都离不开对数据的采集&#xff0c;只有准确的进行了数据采集&#xff0c;才能保证控价结果和分析结果的准确性。所以对于电商数据的采集&#xff0c;其标准也相对比较高。 力维网络有专业稳定的电商数据采集系统&#xff0c;可以多平台、…

二维码智慧门牌管理系统:智能化生活的未来

文章目录 前言一、二维码智慧门牌管理系统的特点二、二维码智慧门牌管理系统的应用三、二维码智慧门牌管理系统的前景 前言 随着科技的不断发展&#xff0c;我们的生活变得越来越智能化。近日&#xff0c;一种名为“二维码智慧门牌管理系统”的新型技术引起了人们的广泛关注。…

10月12日19:30|BIM+GIS用于公路施工组织策划专题直播

当前BIMGIS三维数字沙盘技术成为了交通建设领域的一大热门话题。交通部也在近日发布了《推荐公路数字化转型的意见》&#xff0c;明确指出了BIMGIS技术应用对于公路数字化转型的重要性。那么&#xff0c;公路工程建设施工组织策划阶段&#xff0c;该如何更好地应用BIMGIS技术呢…

C语言--文件操作详解(1)文件操作的基本概念及文件操作函数用法举例

前言 链接: 八功能通讯录 这是我们前面写了通讯录的程序&#xff0c;当通讯录运行起来的时候&#xff0c;可以给通讯录中增加、删除数据&#xff0c;此时数据是存放在内存中&#xff0c;当程序退出的时候&#xff0c;通讯录中的数据自然就不存在了&#xff0c;等下次运行通讯录…

国外SCADA软件比较

讨论工业自动化中使用的各种SCADA软件以及它们之间的比较。 您正在从事一个工业自动化项目&#xff0c;您肯定需要SCADA。很多时候&#xff0c;我们对于需要为应用选择什么是正确的SCADA感到困惑。 因为涉及的因素很多&#xff0c;忽略其中任何一个因素都必然会导致性能出现障…

智能变电站协议转换采集网关BA103

IEC61850该协议是一种用于智能电网通信的协议&#xff0c;它可以实现电力设备信息的实时监测、控制和保护。IEC61850协议具有高效、可靠、快速响应等特点&#xff0c;其数据传输采用面向对象的建模方法&#xff0c;支持多种传输协议和数据格式。在电力系统中&#xff0c;IEC618…

基于SSM的人事档案管理系统(有报告)。Javaee项目。

演示视频&#xff1a; 基于SSM的人事档案管理系统&#xff08;有报告&#xff09;。Javaee项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMvc…

地毯和小地毯16 CFR 1630 和16 CFR 1631表面可燃性标准GCC清关认证

出口美国地垫GCC清关认证 美国联邦法律规定&#xff0c;地毯和垫子要符合易燃性标准和其它要求&#xff0c; 包括2008年《美国消费品安全改进法》的要求。 在地毯和垫子经过检测或合理检测项目后&#xff0c;作为一般用途的 地毯和垫子的生产商和进口商必须在一般合规证书&…

Linux-ubuntu系统查看显卡型号、显卡信息详解

lspci | grep -i vga #----output------ 01:00.0 VGA compatible controller: NVIDIA Corporation Device 2504 (rev a1) PCI devices

计算机竞赛 题目:基于机器视觉的图像矫正 (以车牌识别为例) - 图像畸变校正

文章目录 0 简介1 思路简介1.1 车牌定位1.2 畸变校正 2 代码实现2.1 车牌定位2.1.1 通过颜色特征选定可疑区域2.1.2 寻找车牌外围轮廓2.1.3 车牌区域定位 2.2 畸变校正2.2.1 畸变后车牌顶点定位2.2.2 校正 7 最后 0 简介 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享…

MQ学习笔记

1.MQ基本概念 2.MQ优势 1.服务解耦 **降低服务间耦合性&#xff0c;提升可维护性及扩展性。** 如下图&#xff1a;订单系统发送数据给库存、支付、物流三个系统&#xff0c;但后期又需增加X系统&#xff0c;此时只需X系统自己从MQ获取信息即可&#xff0c;无需改动订单系统代…

2023失业率再创新高,应届生该何去何从?

最新公布的5月份中国就业数据显示&#xff0c;青年人失业率继续上升。国家统计局新闻发言人、国民经济综合统计司司长付凌晖6月15日在北京回应称&#xff0c;随着经济持续好转&#xff0c;就业保持总体稳定有较好支撑。 国务院新闻办公室当天举行5月份国民经济运行情况新闻发布…

Android 多线程并发详解

一&#xff0c;基础概念 1.1什么是CPU 中央处理器&#xff08;CPU&#xff09;&#xff0c;是电子计算机的主要设备之一&#xff0c;电脑中的核心配件。其功能主要是解释计算机指令以及处理计算机软件中的数据。CPU是计算机中负责读取指令&#xff0c;对指令译码并执行指令的…

Vue3最佳实践 第七章 TypeScript 上

​ 在浏览网上的JavaScript相关文档时&#xff0c;大家可能已经注意到了一个趋势&#xff1a;越来越多的项目和教程都采用了TypeScript编写代码。对于那些没有TypeScript经验的人来说&#xff0c;阅读这些由TypeScript编写的代码可能会感到有些压力。   ​Vue3的出现无疑加剧…

SpringBoot 如何使用 Grafana 进行可视化监控

使用Spring Boot Sleuth进行分布式跟踪 在现代分布式应用程序中&#xff0c;跟踪请求和了解应用程序的性能是至关重要的。Spring Boot Sleuth是一个分布式跟踪解决方案&#xff0c;它可以帮助您在分布式系统中跟踪请求并分析性能问题。本文将介绍如何在Spring Boot应用程序中使…

墨西哥专线空加派一条龙服务性价比高吗?

随着全球贸易的不断发展&#xff0c;越来越多的企业开始关注跨境物流&#xff0c;以满足国际市场的需求。墨西哥专线空加派一条龙服务作为一种便捷、高效的物流解决方案&#xff0c;越来越受到企业的青睐。那么&#xff0c;墨西哥专线空加派一条龙服务的性价比高吗?本文将从服…

STM32存储左右互搏 I2C总线FATS读写FRAM MB85RC1M

STM32存储左右互搏 I2C总线FATS读写FRAM MB85RC1M 在较低容量存储领域&#xff0c;除了EEPROM的使用&#xff0c;还有铁电存储器FRAM的使用&#xff0c;相对于EEPROM, 同样是非易失性存储单元&#xff0c;FRAM支持更高的访问速度&#xff0c; 其主要优点为没有EEPROM持续写操作…

基于Spring Boot的网上租贸系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技…

台灯什么材质的比较好?专家推荐的护眼台灯分享

台灯是现在普遍使用的家用照明灯具&#xff0c;不仅可以很好地装饰卧室房间&#xff0c;最主要的作用是可以给我我们补充室内灯源不足的部分&#xff0c;让我们工作、学习等保持极高的专注度&#xff0c;也可以在晚上娱乐休闲时&#xff0c;身心更加愉悦。更重要的是&#xff0…

git操作流程与清单

在团队中的git使用流程 git add git stash push -- src/index.js git pull origin master commit push git stash pop git commit和pull的先后顺序 前辈的原文链接 git stash 优质的原文链接 git stash 将本地部分文件暂存&#xff0c;而不提交到远程仓库 使用 git add …