前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >剑指Offer面试题:25.二叉搜索树与双向链表

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

作者头像
Edison Zhou
发布2018-08-20 16:23:26
3970
发布2018-08-20 16:23:26
举报
文章被收录于专栏:EdisonTalkEdisonTalk

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

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

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

代码语言:javascript
复制
    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 核心步骤

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

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

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

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

2.2 代码实现

代码语言:javascript
复制
    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)辅助方法的封装

代码语言:javascript
复制
    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)功能测试、特殊输入测试

代码语言:javascript
复制
    //            10
    //         /      \
    //        6        14
    //       /\        /\
    //      4  8     12  16
    [TestMethod]
    public void ConvertTest1()
    {
        BinaryTreeNode node10 = new BinaryTreeNode(10);
        BinaryTreeNode node6 = new BinaryTreeNode(6);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node8 = new BinaryTreeNode(8);
        BinaryTreeNode node14 = new BinaryTreeNode(14);
        BinaryTreeNode node12 = new BinaryTreeNode(12);
        BinaryTreeNode node16 = new BinaryTreeNode(16);

        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
    //        /
    //       1
    [TestMethod]
    public void ConvertTest2()
    {
        BinaryTreeNode node5 = new BinaryTreeNode(5);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node3 = new BinaryTreeNode(3);
        BinaryTreeNode node2 = new BinaryTreeNode(2);
        BinaryTreeNode node1 = new BinaryTreeNode(1);

        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
    //        \
    //         5
    [TestMethod]
    public void ConvertTest3()
    {
        BinaryTreeNode node5 = new BinaryTreeNode(5);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node3 = new BinaryTreeNode(3);
        BinaryTreeNode node2 = new BinaryTreeNode(2);
        BinaryTreeNode node1 = new BinaryTreeNode(1);

        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(1);

        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)测试通过情况

  (2)代码覆盖率

作者:周旭龙

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-09-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、题目:二叉搜索树与双向链表
  • 二、解题思路
    • 2.1 核心步骤
      • 2.2 代码实现
      • 三、单元测试
        • 3.1 测试用例
          • 3.2 测试结果
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档