剑指Offer面试题:25.二叉搜索树与双向链表

时间:2022-12-29 07:41:04

一、题目:二叉搜索树与双向链表

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

剑指Offer面试题:25.二叉搜索树与双向链表

  二叉搜索树的节点定义如下,这里使用C#语言描述:

    public class BinaryTreeNode
{
public int Data { get; set; }
public BinaryTreeNode leftChild { get; set; }
public BinaryTreeNode rightChild { get; set; } public BinaryTreeNode(int data)
{
this.Data = data;
} public BinaryTreeNode(int data, BinaryTreeNode left, BinaryTreeNode right)
{
this.Data = data;
this.leftChild = left;
this.rightChild = right;
}
}

二、解题思路

2.1 核心步骤

  首先,我们知道:在二叉树中,每个结点都有两个指向子结点的指针。在双向链表中,每个结点也有两个指针,它们分别指向前一个结点和后一个结点。

  其次,由于要求转换之后的链表是排好序的,我们可以中序遍历树中的每一个结点,这是因为中序遍历算法的特点是按照从小到大的顺序遍历二叉树的每一个结点。

剑指Offer面试题:25.二叉搜索树与双向链表

  最后,按照中序遍历的顺序,当我们遍历转换到根结点(值为10的结点)时,它的左子树已经转换成一个排序的链表了,并且处在链表中的最后一个结点是当前值最大的结点。我们把值为8的结点和根结点链接起来,此时链表中的最后一个结点就是10了。接着我们去遍历转换右子树,并把根结点和右子树中最小的结点链接起来。

  很明显,转换它的左子树和右子树,由于遍历和转换过程是一样的,很自然地想到可以用递归

2.2 代码实现

    public BinaryTreeNode Convert(BinaryTreeNode root)
{
BinaryTreeNode lastNodeInList = null;
ConvertNode(root, ref lastNodeInList); // lastNodeInList指向双向链表的尾结点,
// 我们需要返回头结点
BinaryTreeNode headInList = lastNodeInList;
while (headInList != null && headInList.leftChild != null)
{
headInList = headInList.leftChild;
} return headInList;
} private void ConvertNode(BinaryTreeNode node, ref BinaryTreeNode lastNodeInList)
{
if (node == null)
{
return;
} BinaryTreeNode currentNode = node;
// 转换左子树
if (currentNode.leftChild != null)
{
ConvertNode(currentNode.leftChild, ref lastNodeInList);
}
// 与根节点的衔接
currentNode.leftChild = lastNodeInList;
if (lastNodeInList != null)
{
lastNodeInList.rightChild = currentNode;
}
lastNodeInList = currentNode;
// 转换右子树
if (currentNode.rightChild != null)
{
ConvertNode(currentNode.rightChild, ref lastNodeInList);
}
}

三、单元测试

3.1 测试用例

  (1)辅助方法的封装

    private void SetSubTreeNode(BinaryTreeNode root, BinaryTreeNode lChild, BinaryTreeNode rChild)
{
if (root == null)
{
return;
} root.leftChild = lChild;
root.rightChild = rChild;
} private BSTConverter converter; [TestInitialize]
public void Initialize()
{
converter = new BSTConverter();
} [TestCleanup]
public void CleanUp()
{
converter = null;
}

  (2)功能测试、特殊输入测试

    //            10
// / \
// 6 14
// /\ /\
// 4 8 12 16
[TestMethod]
public void ConvertTest1()
{
BinaryTreeNode node10 = new BinaryTreeNode();
BinaryTreeNode node6 = new BinaryTreeNode();
BinaryTreeNode node4 = new BinaryTreeNode();
BinaryTreeNode node8 = new BinaryTreeNode();
BinaryTreeNode node14 = new BinaryTreeNode();
BinaryTreeNode node12 = new BinaryTreeNode();
BinaryTreeNode node16 = new BinaryTreeNode(); SetSubTreeNode(node10, node6, node14);
SetSubTreeNode(node6, node4, node8);
SetSubTreeNode(node14, node12, node16); BinaryTreeNode result = converter.Convert(node10);
Assert.AreEqual(result, node4);
} // 5
// /
// 4
// /
// 3
// /
// 2
// /
//
[TestMethod]
public void ConvertTest2()
{
BinaryTreeNode node5 = new BinaryTreeNode();
BinaryTreeNode node4 = new BinaryTreeNode();
BinaryTreeNode node3 = new BinaryTreeNode();
BinaryTreeNode node2 = new BinaryTreeNode();
BinaryTreeNode node1 = new BinaryTreeNode(); node5.leftChild = node4;
node4.leftChild = node3;
node3.leftChild = node2;
node2.leftChild = node1; BinaryTreeNode result = converter.Convert(node5);
Assert.AreEqual(result, node1);
} // 1
// \
// 2
// \
// 3
// \
// 4
// \
//
[TestMethod]
public void ConvertTest3()
{
BinaryTreeNode node5 = new BinaryTreeNode();
BinaryTreeNode node4 = new BinaryTreeNode();
BinaryTreeNode node3 = new BinaryTreeNode();
BinaryTreeNode node2 = new BinaryTreeNode();
BinaryTreeNode node1 = new BinaryTreeNode(); node1.rightChild = node2;
node2.rightChild = node3;
node3.rightChild = node4;
node4.rightChild = node5; BinaryTreeNode result = converter.Convert(node1);
Assert.AreEqual(result, node1);
} // 树中只有1个结点
[TestMethod]
public void ConvertTest4()
{
BinaryTreeNode node1 = new BinaryTreeNode(); BinaryTreeNode result = converter.Convert(node1);
Assert.AreEqual(result, node1);
} // 空指针
[TestMethod]
public void ConvertTest5()
{
BinaryTreeNode result = converter.Convert(null);
Assert.AreEqual(result, null);
}

3.2 测试结果

  (1)测试通过情况

剑指Offer面试题:25.二叉搜索树与双向链表

  (2)代码覆盖率

剑指Offer面试题:25.二叉搜索树与双向链表

作者:周旭龙

出处:http://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

剑指Offer面试题:25.二叉搜索树与双向链表的更多相关文章

  1. 剑指Offer:面试题27——二叉搜索树与双向链表(java实现)

    问题描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路: 将树分为三部分:左子树,根结点,右子树. 1.我们要把根结点与左 ...

  2. 剑指offer 面试题36.二叉搜索树与双向链表

    中序递归,一个pre节点记录前一个节点 /* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; Tre ...

  3. 剑指Offer - 九度1503 - 二叉搜索树与双向链表

    剑指Offer - 九度1503 - 二叉搜索树与双向链表2014-02-05 23:39 题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树 ...

  4. 剑指Offer:面试题24——二叉搜索树的后序遍历序列(java实现)

    问题描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 思路: 1.首先后序遍历的结果是[(左子 ...

  5. 剑指offer(26)二叉搜索树与双向链表

    题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 题目分析 要生成排序的双向列表,那么只能是中序遍历,因为中序遍历才能从小到 ...

  6. 【剑指Offer】26、二叉搜索树与双向链表

      题目描述:   输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向.   解题思路:   首先要理解此题目的含义,在双向链表中,每个结 ...

  7. 剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列

    剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列2013-11-23 03:16 题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出 ...

  8. 剑指offer(20)二叉搜索树与双向表

    题目: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路一:递归法 1.将左子树构造成双链表,并返回链表头节点. 2.定位至左子 ...

  9. 剑指offer(23)二叉搜索树的后序遍历序列

    题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 题目分析 1.后续遍历我们可以知道,最右边的是根节 ...

  10. 剑指offer(62)二叉搜索树的第K个节点

    题目描述 给定一棵二叉搜索树,请找出其中的第k小的结点.例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4. 题目分析 首先,我们可以先画图.画完图后我们要想办法从 ...

随机推荐

  1. 批量处理sql 数据存入xml类型列

    个人记录 需求:当表T1 ItemCode和表T2 ItemName的数据相等时,将表T2所对应的ID和ItemName列的数据分别存入表T1 CAOZUO字段的id元素和text元素的文本中. 下面 ...

  2. 看看Parallel中高度封装的三个方法,Invoke,For和ForEach

    说到.net中的并行编程,也许你的第一反应就是Task,确实Task是一个非常灵活的用于并行编程的一个专用类,不可否认越灵活的东西用起来就越 复杂,高度封装的东西用起来很简单,但是缺失了灵活性,这篇我 ...

  3. 搭建一个免费的,无限流量的Blog----github Pages和Jekyll入门

    喜欢写Blog的人,会经历三个阶段. 第一阶段,刚接触Blog,觉得很新鲜,试着选择一个免费空间来写. 第二阶段,发现免费空间限制太多,就自己购买域名和空间,搭建独立博客. 第三阶段,觉得独立博客的管 ...

  4. linux nandflash驱动之MTD层

    MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口.MTD将文件系统与底层FLASH存储 ...

  5. 转:测试用书(出处:cnblog--liangshi)

    列表格式为:图书分类.中文书名.英文书名.作者.排名不分先后,用红色标记出我推荐的书籍. 测试入门 软件测试(第2版) Software Testing (2e), Ron Patton 一本测试入门 ...

  6. NYOJ--714--Card Trick

    /* Name: NYOJ--714--Card Trick Author: shen_渊 Date: 19/04/17 19:35 Description: 早上训练的第六届河南省程序设计大赛的题, ...

  7. NumPy简介

    NumPy是什么? NumPy(Numerrical Python 的缩写)是一个开源的Python科学计算库.使用NumPy,就可以很自然的使用数组.NumPy包含很多实用的数学函数,涵盖线性代数运 ...

  8. [转]Blue Prism Login Agent 使用指导手册

    本文转自:https://cloud.tencent.com/developer/news/83035 咳!咳!咳! 第一篇RPA技术文,还是贼拉鸡冻.各位大侠要多多支持啊 1.Login Agent ...

  9. c语言经典小程序

    1:题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. mai ...

  10. kubectl批量删除pvc

    #!/bin/bashkubectl get pvc |grep hub > tmp.txtcat tmp.txt |awk '{split($0,a," ");print ...