Java 查找二叉树中某一结点的前驱结点以及后继结点

news2024/10/7 4:28:33

文章目录

    • 前言
      • 什么是后继结点
      • 什么是前驱结点
    • 代码实现
      • 查找某一结点的后继结点
        • 思路
        • 代码实现
        • 图解
      • 查找某一结点的前驱结点
        • 思路
        • 代码实现
        • 图解
    • 测试用例
      • 运行结果
    • 结语

前言

给定二叉树结点定义Node结构如下,其中parent结点指向当前Node结点的父结点,根结点指向null

    private static class Node {
        public int value;
        public Node left;
        public Node right;
        /**
         * 指向父结点,头结点指向null
         */
        public Node parent;

        public Node(int value) {
            this.value = value;
        }
    }

什么是后继结点

定义:在二叉树的中序遍历的序列中,Node的下一个节点叫作Node的后继节点。

什么是前驱结点

定义:在二叉树的中序遍历的序列中,Node的前一个节点叫作Node的前驱节点。

代码实现

查找某一结点的后继结点

思路

根据中序遍历的顺序可以得出如下结论:

  1. 如果该结点存在右子树,则该结点对应的后继结点为其右子树上最左的结点;
  2. 如果该结点不存在右子树,向上查找,如果某个结点的parent结点的左子树等于该node结点,则此parent结点为后继结点

代码实现

 /**
     * 获取某个结点的后继结点
     *
     * @param node
     * @return
     */
    private static Node getSuccessorNode(Node node) {
        if (node == null) {
            return node;
        }
        if (node.right != null) {
            //1.当node结点存在右子树,则后继结点为Node结点右子树最左边结点
            return getLeftMost(node.right);
        } else {
            //当前Node结点没有右子树,则向上查找;
            //某个结点的parent结点的左子树 == node结点,则此parent结点即为后继结点
            Node parent = node.parent;
            while (parent != null && parent.left != node) {
                node = parent;
                parent = node.parent;
            }
            return parent;

        }
    }
    
   /**
     * 获取某个结点最左结点
     *
     * @param node
     * @return
     */
    private static Node getLeftMost(Node node) {
        if (node == null) {
            return node;
        }
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

图解

后继结点查找

查找某一结点的前驱结点

思路

与查找后继结点相类似,根据中序遍历顺序同样可以得出如下结论:

  1. 如果该结点存在左子树,则该结点对应的前驱结点为其左子树上最右的结点;
  2. 如果该结点不存在左子树,向上查找,如果某个结点的parent结点的右子树等于该node结点,则此parent结点为前驱结点

代码实现

    /**
     * 获取某一Node结点对应的前驱结点
     *
     * @param node
     * @return
     */
    private static Node getPrecursorNode(Node node) {
        if (node == null) {
            return node;
        }
        if (node.left != null) {
            //1.当node结点存在左子树,则前驱结点为Node结点左子树最右边结点
            return getRightMost(node.left);
        } else {
            //当前Node结点没有左子树,则向上查找;
            //某个结点的parent结点的右子树 == node结点,则此parent结点即为后继结点
            Node parent = node.parent;
            while (parent != null && parent.right != node) {
                    node = parent;
                    parent = node.parent;
            }
            return parent;
        }
    }

  /**
     * 获取某一结点最右结点
     *
     * @param node
     */
    private static Node getRightMost(Node node) {
        if (node == null) {
            return node;
        }
        while (node.right != null) {
            node = node.right;
        }
        return node;
    }

图解

查找某一结点的前驱结点

测试用例

  public static void main(String[] args) {
        Node node = new Node(1);
        node.parent = null;

        node.left = new Node(2);
        node.left.parent = node;

        node.right = new Node(3);
        node.right.parent = node;

        node.left.left = new Node(4);
        node.left.left.parent = node.left;

        node.left.right = new Node(5);
        node.left.right.parent = node.left;

        node.left.right.left = new Node(6);
        node.left.right.left.parent = node.left.right;

        node.left.right.right = new Node(7);
        node.left.right.right.parent = node.left.right;
        Node target = node.left.right.left;
        System.out.println(target.value + "的后继结点为:" + getSuccessorNode(target).value);
        System.out.println(target.value + "的前驱结点为:" +getPrecursorNode(target).value);
    }

运行结果

6的后继结点为:5
6的前驱结点为:2

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

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

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

相关文章

c++ 资源文件打包exe 写出指定目录

#include <iostream> #include <fstream> #include <Windows.h>int main() {// 加载资源HMODULE hModule GetModuleHandle(NULL);// HRSRC hResource FindResource(hModule, MAKEINTRESOURCE(IDR_MYSYS), RT_RCDATA);// IMAGE 是添加资源文件时起的名字HRS…

BOSHIDA DC电源模块过载保护的原理

BOSHIDA DC电源模块过载保护的原理 DC电源模块过载保护的原理是通过电路设计和控制算法来实现的&#xff0c;其基本思想是在系统发生过载时&#xff0c;通过控制电路的工作状态和输出特性&#xff0c;实现对输出电流的限制和保护。 具体来说&#xff0c;DC电源模块的过载保护主…

智慧城市建设与数字孪生技术的紧密关联

智慧城市是当今社会发展的趋势&#xff0c;它通过智能技术和数字化手段&#xff0c;实现城市各个领域的高效运行和可持续发展。而数字孪生技术作为智慧城市建设的重要支撑&#xff0c;正在发挥着重要的作用。 首先&#xff0c;数字孪生技术在城市规划和设计方面发挥着重要作用…

【C语言】4-C语言的数据表现形式之数据类型

0. 引言 在之前的例子中可以看到&#xff0c;在定义变量时需要指定变量的类型。C 语言要求在定义所有的变量与常量时都要指定变量的类型 为什么在用计算机运算时要指定数据的类型呢&#xff1f;在数学中&#xff0c;数值是不分类型的&#xff0c;数值的运算是绝对准确的&#…

重塑未来的1课:组装式交付新引擎——华为云智能化低代码平台

HDC期间可参与Astro注册抽奖&#xff0c;活动详情见文末&#xff01; 紧跟低代码技术飞速发展——华为云Astro智能工作流惊艳HDC.Cloud 2023&#xff01; 企业对未来智能化组装式交付的期待已不是空想。智能化低代码即将重新定义传统交付模式&#xff0c;密切连接AI科技与创造…

ue4 MRQ渲染器时,媒体纹理播放速度会被加快

问题描述&#xff1a;当MRQ渲染器开启抗锯齿时&#xff0c;媒体纹理的播放速度会被加快 解决办法&#xff1a;通过执行抗锯齿控制台命令来解决

手写文字识别为何这么难?怎么应对?

手写文字识别是一项极具挑战性的任务&#xff0c;它之所以比识别印刷体文字难&#xff0c;笔者认为&#xff0c;主要原因在于以下几个方面&#xff1a; 首先&#xff0c;手写文字样式的多样性是识别难度的主要来源。我们知道&#xff0c;签名具有法律效力&#xff0c;为什么呢…

前端|项目实操流程|学成在线项目实操

参考视频&#xff1a;黑马程序员前端CSS3基础教程&#xff0c;前端必备基础 目录 &#x1f4da;案例准备工作 &#x1f4da;CSS属性书写顺序 &#x1f407;布局定位属性 &#x1f407;自身属性 &#x1f4da;页面布局整体思路 &#x1f4da;学成在线项目制作 &#x1f4…

ELK 企业级日志分析系统的概念、ELK Elasticsearch 集群部署

ELK 企业级日志分析系统 一、ELK 的概述1、ELK 简介2、可以添加的其它组件3、filebeat 结合 logstash 带来好处&#xff1a;4、Fluentd的概念 二、ELK的特征与工作原理1、为什么要使用 ELK2、完整日志系统基本特征3、ELK 的工作原理 三、ELK Elasticsearch 集群部署&#xff08…

设计模式——门面模式

门面模式 定义 门面模式&#xff08;Faade Pattern&#xff09;又称为外观模式&#xff0c;是一种比较常用的封装模式。 要求一个子系统的外部与其内部的通信通过一个统一的对象进行。门面模式提供一个高层次的接口&#xff0c;使得子系统更易于使用 优缺点、应用场景 优点…

关于VUE报错“TypeError: Converting circular structure to JSON“

关于VUE报错“TypeError: Converting circular structure to JSON" 问题&#xff1a; [Vue warn]: Error in nextTick: "TypeError: Converting circular structure to JSON--> starting at object with constructor Vue| property $options -> object wit…

Linux驱动进阶(二)——设备驱动中的阻塞和同步机制

文章目录 前言阻塞与非阻塞等待队列等待队列概述等待队列的实现等待队列的使用 同步机制实验同步机制设计实验验证 小结 前言 阻塞和非阻塞是设备访问的两种基本方式。使用这两种方式&#xff0c;驱动程序可以灵活地支持阻塞与非阻塞访问。在写阻塞与非阻塞的驱动程序时&#…

喜报!Coremail连续4届入选嘶吼网络安全产业图谱

7月10日&#xff0c;嘶吼安全产业研究院联合国家网络安全产业园区&#xff08;通州园&#xff09;正式发布《嘶吼2023网络安全产业图谱》&#xff08;以下简称“图谱”&#xff09;。 Coremail成功入选本次图谱五大分类下14个细分领域&#xff0c;分别是安全自动化/协作&#x…

linux中数据库表相关查询

目录 1.显示所有职工的基本信息 2.查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号 3.求出所有职工的人数 4.列出最高工资和最低工资 5.列出职工的平均工资和总工资 6.创建一个只有职工号&#xff0c;姓名和参加工作的新表&#xff0c;名为工作日期表 7、显示所…

GPT(Generative Pre-Training)论文解读及实现(一)

1 GPT Framework 1.1 Unsupervised pre-training Given an unsupervised corpus of tokens U {u1, . . . , un}, we use a standard language modeling objective to maximize the following likelihood: 在给定语料上下文环境下&#xff0c;目标时最大化下面的语言模型&…

Java8 Stream 使用详解

Java8 Stream 使用详解 一、流的定义二、流的创建1. 通过集合创建流&#xff1a;2. 通过数组创建流&#xff1a;3. 通过Stream.of()创建流&#xff1a;4. 通过Stream.generate()创建流&#xff1a;5. 通过Stream.iterate()创建流&#xff1a;6. 通过文件、网络、IO流等方式来创…

Effective Java 高效编码阅读 笔记

《Effective Java》 有关于 Java 变成编程性能优化的 的书籍&#xff0c;看了不计其数 &#xff0c;但是每当读起来能让我眼前一亮的还得是 Effective Java 像这一类的书籍还有很多例如下面的 的两本&#xff0c;今天呢&#xff0c;来记录下此书的阅读笔记方便日后记忆&#xf…

【面试题34】什么是MVC,为什么要使用它

文章目录 一、前言二、MVC介绍2.1 模型&#xff08;Model&#xff09;2.2 视图&#xff08;View&#xff09;2.3 控制器&#xff08;Controller&#xff09; 三、MVC模式的优点四、总结 一、前言 本文已收录于PHP全栈系列专栏&#xff1a;PHP面试专区。 计划将全覆盖PHP开发领域…

深入了解Spring Cloud的服务注册与发现组件Eureka

摘要&#xff1a;Spring Cloud是一个基于Spring框架的开发工具包&#xff0c;可以帮助开发人员构建基于微服务架构的分布式系统。其中的核心组件之一是Eureka&#xff0c;它提供了一套强大的服务注册与发现功能。本文将深入介绍Spring Cloud中的Eureka组件&#xff0c;包括其背…

MIT 6.S081 -- Networking

MIT 6.S081 -- Networking 引言计算机网络概述二层网络 --- Ethernet二/三层地址转换 --- ARP三层网络 --- Internet四层网络 --- UDP网络协议栈&#xff08;Network Stack&#xff09;Ring BufferReceive Livelock如何解决Livelock 引言 本文整理至: MIT 6.S081 2020 操作系统…