首页 > 其他分享 >二叉搜索树与双向链表 剑指offer

二叉搜索树与双向链表 剑指offer

时间:2024-12-17 20:30:06浏览次数:5  
标签:左子 offer 右子 值为 二叉 链表 二叉树 节点

题目描述

        输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。比如,输入下图中左边的二叉搜索树,则输出转换之后的排序双向链表。

        树节点的定义如下:

 题目分析

        在二叉树中,每个节点都有两个指向子节点的指针。在双向链表中,每个节点也有两个指针,分别指向前一个节点和后一个节点。由于这两种节点的结构相似,同时二叉搜索树也是一种排序的数据结构,因此,在理论上有可能实现二叉搜索树和排序双向链表的转换。在搜索二叉树中,左子节点的值总是小于父节点的值,右子节点的值总是大于父节点的值。因此,我们在将二叉搜索树转换成排序双向链表时,原先指向左子节点的指针调整为链表中指向前一个节点的指针,原先指向右子节点的指针调整为链表中指向后一个节点的指针。接下来我们考虑该如何转换。
        由于要求转换之后的链表是排好序的,我们可以中序遍历树中的每个节点,这是因为中序遍历算法的特点是按照从小到大的顺序遍历二叉树的每个节点。当遍历到根节点的时候,我们把树看成3部分:值为10的节点;根节点值为6的左子树;根节点值为14的右子树。根据排序链表的定义值为10的节点将和它的左子树的最大一个节点(值为8的节点)链接起来,同时它还将和右子树最小的节点(值为12的节点)链接起来,如下图所示。

        按照中序遍历的顺序,当我们遍历转换到根节点(值为10的节点)时,它的左子树已经转换成一个排序的链表了,并且处在链表中的最后一个节点是当前值最大的节点。我们把值为8的节点和根节点链接起来,此时链表中的最后一个节点就是10了。接着我们去遍历转换右子树,并把根节点和右子树中最小的节点链接起来。至于怎么去转换它的左子树和右子树,由于遍历和转换过程是一样的,我们很自然地想到可以用递归。 

代码实现

代码解释

        在上面的代码中,我们用 pLastNodeInList 指向已经转换好的链表的最后一个节点(值最大的节点)。当我们遍历到值为10的节点的时候,它的左子树都已经转换好了,因此pLastNodeInList指向值为8的节点。接着把根节点链接到链表中之后,值为10的节点成了链表中的最后一个节点(新的值最大的节点),于是 pLastNodeInList 指向了这个值为 10 的节点。接下来把 pLastNodeInList 作为参数传入函数递归遍历右子树。我们找到右子树中最左边的子节点(值为12的节点,在右子树中值最小),并把该节点和值为 10 的节点链接起来。

测试用例

        功能测试(输入的二叉树是完全二叉树;所有节点都没有左/右子树的二叉树;只有一个节点的二叉树)。
        特殊输入测试(指向二叉树根节点的指针为 nullptr 指针)。

本题考点

        考查应聘者分析复杂问题的能力。无论是二叉树还是双向链表,都有很多指针。要实现这两种不同数据结构的转换,需要调整大量的指针,因此这个过程会很复杂。为了把这个复杂的问题分析清楚,我们可以把树分为3部分:根节点、左子树和右子树,然后把左子树中最大的节点、根节点、右子树中最小的节点链接起来。至于如何把左子树和右子树内部的节点链接成链表,那和原来的问题的实质是一样的,因此可以递归解决。解决这个问题的关键在于把一个大的问题分解成几个小问题,并递归地解决小问题。
        考查应聘者对二叉树和双向链表的理解及编程能力。

标签:左子,offer,右子,值为,二叉,链表,二叉树,节点
From: https://blog.csdn.net/2301_78353179/article/details/144516770

相关文章

  • 二叉树中和为某一值的路径 剑指offer
    题目描述        输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。        二叉树节点的定义如下:题目分析                分析完前面具体的例子......
  • 链表操作(前驱和后继)
     题目描述设计函数void prevnext(structnode*head,charx);,在以head为头指针的非空链表中,找到数据域值为x的结点,输出该结点的前一个结点和后一个结点的数据域值,如果该结点没有前驱结点(即该结点为第1个结点),则以-1代替,如果该结点没有后继结点(即该结点为尾结点),也以-1......
  • c语言链表头插法再汇总
    建议回顾c链表一系列操作(主要是尾插法)c链表头插法遍历函数在这里先把尾插法的遍历函数稍作修改拿过来。voidForeach(NODE*h){if(NULL==h){return;}//辅助指针变量(帽子)NODE*pC=h;//这里改动是因为没有第一个空节点了......
  • 【华为OD-E卷-寻找链表的中间结点 100分(python、java、c++、js、c)】
    【华为OD-E卷-寻找链表的中间结点100分(python、java、c++、js、c)】题目给定一个单链表L,请编写程序输出L中间结点保存的数据。如果有两个中间结点,则输出第二个中间结点保存的数据。例如:给定L为1→7→5,则输出应该为7;给定L为1→2→3→4,则输出应该为3;输入描述......
  • 二叉树的右视图
    二叉树的右视图描述给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。示例:输入:[1,2,3,null,5,null,4]输出:[1,3,4]解释:1<---/\23<---\\54<---代码1(错误)......
  • 二叉搜索树 & 平衡树(c嘎嘎版)
    定义:二叉搜索树是一种二叉树的树形数据结构,其定义如下:空树是二叉搜索树。若二叉搜索树的左子树不为空,则其左子树上所有点的附加权值均小于其根节点的值。若二叉搜索树的右子树不为空,则其右子树上所有点的附加权值均大于其根节点的值。二叉搜索树的左右子树均为二......
  • 【LC】141. 环形链表
    题目描述:给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从0开始)。注意:pos 不作为参数进行传递 。......
  • 之字形打印二叉树 剑指offer
    题目描述       请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。例如,按之字形顺序打印下图二叉树的结果为:题目分析       按之字形顺序打印二叉树需要......
  • Java程序员面试1000问,花点耐心看完offer拿到手软
    前言:本文收集整理了各大厂常见面试题N道,你想要的这里都有内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、SpringBoot、SpringCloud、RabbitMQ、Kafka、Linux等技术栈,希望大家都能找到适合自己的公司,开开心心的撸代码。目录:......
  • 算法之链表
    链表移除链表元素对于链表来说,删除头节点和中间节点具体操作不一样是因为想要删除一个中间节点,必须要知道该节点的前一个节点,而头节点没有前一个节点。  使用虚拟头节点,统一节点的删除操作,用一个虚拟头节点的next指向head,这个链表中的每个元素都会有前一个节点,从而对所有节点......