数据结构与算法--二叉查找树转顺序排列双向链表

二叉查找树转顺序排列双向链表

  • 题目:输入一颗二叉查找树,将二叉查找树转成一个排序的双向链表,要求不能创建任何新节点,只调整树节点中指针的指向。例如下图所示:
    在这里插入图片描述
  • 本次二叉查找树节点定义使用之前文章 数据结构与算法–二叉查找树实现原理中节点定义,下文中相关api实现同样使用该文中的方法,文中对二叉查找树相关的api有详细的说明推演,如有问题可到文中查看。节点实例如下:
/*** 二叉树节点对象定义** @author liaojiamin* @Date:Created in 15:24 2020/12/11*/
public class BinaryNode implements Comparable {private Object element;private BinaryNode left;private BinaryNode right;private int count;
............
  • 理论基础:

    • 二叉树中节点与双向链表的节点都存在两个指针,只是指向不同而已。
    • 二叉搜索树中左子节点总是小于主节点,右子节点总是大于主节点,在中序遍历中就是顺序的将每个节点读取
    • 那么我们通过中序遍历的思想将二叉查找树转顺序双向链表,将原先指向左节点的指针调整为链表的指向前一个节点,指向右节点的指针指向后一个节点
    • 如上方式得到我们转换的结果
  • 问题分析:

    • 有关树的题型我们必然会想到递归的,有树遍历必有递归,再者递归必然只考虑最简单情况,这样不至于将自己绕进去
    • 考虑三层节点最简单情况,如上图中,分三部分 10 根节点,6 为根节点的左子树,14 为根节点的右子树
    • 根据链表定义,10 节点将和左子树的8 链接,和右子树的12 链接
    • 也就是中序遍历的顺序 (4,6,8)–> 10 -->(12,14,16)
    • 左子树为例,只需要增加两个指针指向,4–>6, 8–>6 两个指针,最后返回8 节点
    • 记录当前节点为current,pLastNodeInList指向需要改变指向的节点,当递归到current = 6,左子树pLastNodeInList指向最小节点4,只需要增加指针指向current.setleft = pLastNodeInList && pLastNodeInList.right=current,其实第一个是已经存在的,但是仅仅是左节点情况存在,我们左右节点统一处理,这样用一个递归解决。接着回到上一节点pLastNodeInList = current = 6,
    • 继续递归右子树,current=8, current.left = pLastNodeInList = 6 && pLastNodeInList .right = current, 此处第二步骤指针已经存在,同样统一处理。
    • 那么我们将每一个左,右子树用同样规则递归处理得到最终的结果,我们最终返回pLastNodeInList ,指向root节点
    • 在递归left方向得到链表头
  • 图解分析:

在这里插入图片描述

  • 通过如上分析有如下代码:
/*** 二叉查找树转顺序排列的双向链表** @author liaojiamin* @Date:Created in 14:27 2021/5/19*/
public class ConvertBinaryToList {public static void main(String[] args) {BinaryNode node = new BinaryNode(null, null, null);BinarySearchTree searchTree = new BinarySearchTree();Random random = new Random();for (int i = 0; i < 8; i++) {node = searchTree.insert(random.nextInt(100), node);}printMiddle(node);BinaryNode doubleLink = convertBinary(node);BinaryNode headNode = doubleLink;while (headNode.getLeft() != null) {headNode = headNode.getLeft();}while (headNode.getRight() != null) {System.out.print("value: " + headNode.getElement());System.out.print("left: " + (headNode.getLeft() != null ? headNode.getLeft().getElement() : ""));System.out.print("right: " + (headNode.getRight() != null ? headNode.getRight().getElement() : ""));System.out.println();headNode = headNode.getRight();if(headNode.getRight() == null ){System.out.print("value: " + headNode.getElement());System.out.print("left: " + (headNode.getLeft() != null ? headNode.getLeft().getElement() : ""));System.out.print("right: " + (headNode.getRight() != null ? headNode.getRight().getElement() : ""));}}}/*** 二叉查找树转双向链表,顺序* 递归处理后,找出最左节点*/public static BinaryNode convertBinary(BinaryNode root) {BinaryNode pLastNodeInList = null;pLastNodeInList = convertNode(root, pLastNodeInList);BinaryNode pHeadOfLast = pLastNodeInList;while (pHeadOfLast != null && pHeadOfLast.getLeft() != null) {pHeadOfLast = pHeadOfLast.getLeft();}return pHeadOfLast;}public static BinaryNode convertNode(BinaryNode node, BinaryNode pLastNodeInList) {if (node == null) {return pLastNodeInList;}BinaryNode current = node;if (current.getLeft() != null) {//递归左节点pLastNodeInList = convertNode(current.getLeft(), pLastNodeInList);}//此时node节点是根,将左子树的最大节点pLastNodeInList 设置为根的left节点current.setLeft(pLastNodeInList);if (pLastNodeInList != null) {//此时的pLastNodeInList 是左子树的最大节点,他的right应该是root,也就是当前的currentpLastNodeInList.setRight(current);}//此时左节点干完,左节点的最大节点是当前root也就是currentpLastNodeInList = current;//递归右节点if (current.getRight() != null) {pLastNodeInList = convertNode(current.getRight(), pLastNodeInList);}return pLastNodeInList;}/*** 中序遍历*/public static void printMiddle(BinaryNode root) {if (root == null || root.getElement() == null) {return;}printMiddle(root.getLeft());System.out.println(root.getElement());printMiddle(root.getRight());}}

上一篇:数据结构与算法–复杂链表的复制
下一篇:数据结构与算法–字符串的排列组合问题

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

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

相关文章

5种避免C#.NET中因事件造成内存泄漏的技术

原文来自互联网&#xff0c;由长沙DotNET技术社区编译。 5种避免C&#xff03;.NET中事件造成的内存泄漏的技术C&#xff03;&#xff08;通常是.NET&#xff09;中的事件注册是内存泄漏的最常见原因。至少从我的经验来看。实际上&#xff0c;我从事件中看到了太多的内存泄漏&a…

数据结构与算法--字符串的排列组合问题

字符串的全排列 题目&#xff1a;输入一个字符串&#xff0c;打印出改字符串中所有字符的所有排列。例如输入字符串abc&#xff0c;那么打印出由a&#xff0c;b&#xff0c;c字符组成的所有字符串&#xff1a;abc&#xff0c;acb&#xff0c;bac&#xff0c;bca&#xff0c;cab…

[GitHub] 75+的 C# 数据结构和算法实现

C#中标准数据结构和算法的即插即用类库项目GitHub&#xff1a;https://github.com/aalhour/C-Sharp-AlgorithmsWatch: 307 Star: 3.4k Fork: 910o---o | |/ --O---O--O | |\ --O---O--o---o | |O o o--o o--o o---o o-O-o …

我是如何一步步的在并行编程中将lock锁次数降到最低实现无锁编程

在并行编程中&#xff0c;经常会遇到多线程间操作共享集合的问题&#xff0c;很多时候大家都很难逃避这个问题做到一种无锁编程状态&#xff0c;你也知道一旦给共享集合套上lock之后&#xff0c;并发和伸缩能力往往会造成很大影响&#xff0c;这篇就来谈谈如何尽可能的减少lock…

常用Arthas命令

jad反编译 检查线上代码是否修改成功&#xff0c;例如修改interface后看Jar包是否引入新的&#xff0c;或者代码是否最新的。 jad com.zhenai.counseling.business.provider.facade.supremecourse.RedeemRecordFacadeImpl //反编译只展示源码 jad --source-only com.zhenai.c…

关于分布式锁的面试题都在这里了

「我今天班儿都没上&#xff0c;就为了赶紧把这篇文章分布式锁早点写完。我真的不能再贴心了。」「边喝茶边构思&#xff0c;你们可不要白嫖了&#xff01;三连来一遍&#xff1f;」引言为什么要学习分布式锁&#xff1f;最简单的理由就是作为一个社招程序员&#xff0c;面试的…

Git 15周年:当年的分道扬镳,成就了今天的开源传奇

4 月 7 日&#xff0c;全球最主流的版本控制系统 —— Git 迎来 15 周年纪念日&#xff0c;项目主要维护者 Junio C Hamano&#xff08;滨野 纯&#xff09; 先生发邮件庆祝了这一日子。我们知道&#xff0c;所有的软件项目在整个生命周期中都要经过不断迭代&#xff0c;在一个…

使用 docker 编译运行 abp 项目

在前面的两篇文章中&#xff0c;介绍了如何在华为鲲鹏架构及其Euler系统上运行dotnet core, 使用docker运行了默认的mvc模板项目&#xff0c;这篇文章继续介绍在docker中运行更复杂的dotnet core项目&#xff0c;这里以业内鼎鼎大名的abp vnext框架&#xff0c;版本 2.6 为例。…

数据结构与算法--数组中的逆序对

题目&#xff1a;在数组中的两个数字如果签名一个数字大于后面的数组&#xff0c;则这两个数字组成一个逆序对。输入一个数组&#xff0c;求出这个数组中的逆序对的总数。 案例&#xff1a;输入数组{7,5&#xff0c;6,4}中一共有5个逆序对分别是{7,6}&#xff0c;{7,5}&#x…

用了这么多年的泛型,你对它到底有多了解?

现代程序员写代码没有人敢说自己没用过泛型&#xff0c;这个泛型模板T可以被任何你想要的类型替代&#xff0c;确实很魔法很神奇&#xff0c;很多人也习以为常了&#xff0c;但就是这么有趣的泛型T底层到底是怎么帮你实现的&#xff0c;不知道有多少人清楚底层玩法&#xff0c;…

数据结构与算法--两个链表中第一个公共节点

链表中第一个公共节点 公节点定义&#xff1a;同一个节点在两个链表中&#xff0c;并不是节点值相同题目&#xff1a;输入两个节点&#xff0c;找出他们的第一个公共节点&#xff0c;节点定义如需 /*** 链表元素节点** author liaojiamin* Date:Created in 12:17 2021/3/5*/ …

ASP.NET Core技术研究-全面认识Web服务器Kestrel

因为IIS不支持跨平台的原因&#xff0c;我们在升级到ASP.NET Core后&#xff0c;会接触到一个新的Web服务器Kestrel。相信大家刚接触这个Kestrel时&#xff0c;会有各种各样的疑问。今天我们全面认识一下ASP.NET Core的默认Web服务器Kestrel。一、初识Kestrel首先&#xff0c;K…