此题为July在CSDN发布的微软编程面试100题中的第一题,觉得蛮有趣的,今天也拿过来玩玩,July的代码用的是C++实现,可能因为有指针的原因吧,感觉看起来相对比较容易理解整个的实现过程,而我,试着用C#完成这样的功能。

完整的题目如下:

把二元查找树转变成排序的双向链表,要求不能创建任何新的结点,只调整指针的指向。

10

/   \

6    14

/ \    / \
4 8  12 16

转换成双链表  4=6=8=10=12=14=16

动手编码之前,先回顾下二叉查找树的特点:任意节点的左子树都要小于当前节点,右子树都要大于当前节点。查询某个值,需要的时间复杂度为O(lgN)

现在要求将其由树状结构改造成线性结构的双向链表,重点在于,获得当前节点左子树范围内最右节点(也是左子树最大值节点),以及右子树范围内最左节点(也是右子树最小值节点),然后,调整这两个节点当前节点左右顺序。即调整8、10之间和12、10之间的关系。

算法思路:

  1. 树根节点,分左右子树。先将当前节点左子树范围内最右节点leftR找出来,再将右子树范围内最左节点rightL找出来(这两步放在一开始,因为此时左右子树内的关系还没改变,先取出来,时间消耗O(lgN)。只是查找到节点,空间上只用到一个索引,不会产生新的内存分配)。
  2. 若左子树为叶子节点,则直接设置其右向索引指向其父节点,左向递归结束;否则,将此节点作为根节点,递归调用第一步。
  3. 若右子树为叶子节点,则直接设置其左向索引指向其父节点,右向递归结束,否则,将此节点作为根节点,递归调用第一步。
  4. 设置根节点的左向节点为leftR,leftR的右向节点为根节点(其左向节点,在b和c两步的递归过程中已经赋值),设置根节点的右向节点为rightL,rightL的左向节点为根节点(其右向节点,在b和c两步的递归过程中已经赋值)

C#源码部分:

首先定义根节点和左右子树节点:

        private int value;
private MyLinkedNode left;
private MyLinkedNode right; public MyLinkedNode(int value)
{
this.value = value;
} public MyLinkedNode Left
{
get { return this.left; }
set { this.left = value; }
} public MyLinkedNode Right
{
get { return this.right; }
set { this.right = value; }
}

以下代码为逻辑递归代码:

        private static void ProcessTreeToLinked(MyLinkedNode node)
{
if (null==node)
{
return;
} //获取左子树的最右节点
MyLinkedNode leftR = getMostRightNode(node.Left); //获取右子树的最左节点
MyLinkedNode rightL = getMostLeftNode(node.Right); //左子树非空,递归处理左子树
if (null == node.Left)
{
ProcessLeftNode(node.Left, node);
} //若右子树非空,递归处理右子树
if (null == node.Right)
{
ProcessRightNode(node.right, node);
} //若左子树最右节点非空,调整与根节点相邻
if (null != leftR)
{
leftR.Right = node;
node.Left = leftR;
} //若右子树的最左节点非空,调整与根节点相邻
if (null != rightL)
{
rightL.Left = node;
node.Right = rightL;
}
} private static void ProcessRightNode(MyLinkedNode right, MyLinkedNode node)
{
//若右子树为叶子节点,直接将其左向索引指向父节点,并返回
if (isLeafNode(right))
{
right.Left = node;
return;
} ProcessTreeToLinked(right);
} private static void ProcessLeftNode(MyLinkedNode left, MyLinkedNode node)
{
//若左子树为叶子节点,直接将其右向索引指向父节点,并返回
if (isLeafNode(left))
{
left.Right = node;
return;
} //本节点当作根节点,递归调用
ProcessTreeToLinked(left);
} private static bool isLeafNode(MyLinkedNode node)
{
return (null == node.Left) && (null == node.Right);
} private static MyLinkedNode getMostLeftNode(MyLinkedNode right)
{
if (null == right)
{
return null;
} if (null == right.Left)
{
return right;
} return getMostLeftNode(right.Left);
} private static MyLinkedNode getMostRightNode(MyLinkedNode left)
{
if (null==left)
{
return null;
} if (null==left.Right)
{
return left;
} return getMostRightNode(left.Right);
}

  

编写这段代码其实不难,难的是如何理清楚解题思路。权当为接下来的面试做准备了,上次面试被问到要实现String.Replace()方法,却不能调用API,不得不说,作为一名测试人员,这样的编码难度对我来说还是比较大的,但并非不可克服,只是,需要继续努力提升自己~轻轻地,对自己说一声,加油~

二元查找树转变成排序的双向链表之C#算法实现的更多相关文章

  1. MS - 1 - 把二元查找树转变成排序的双向链表

    ## 1. 把二元查找树转变成排序的双向链表 ## ### 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表. ### 要求不能创建任何新的结点,只调整指针的指向. 10       ...

  2. 【Data structure & Algorithm】把二元查找树转变成排序的双向链表

    把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表,要求不能创建任何新节点,只调整指针指向. 比如将二元查找树 10 /       \ 6       ...

  3. 1.把二元查找树转变成排序的双向链表[BST2DoubleLinkedList]

    [题目]:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向. 比如将二元查找树 . 10 / \ 6 14 / \ / \ 4 8 12 16 转 ...

  4. IT公司100题-15-求二元查找树的镜像

    问题描述: 输入一颗二元查找树,将该树转换为它的镜像树,即对每一个节点,互换左右子树.   例如输入:   6/    \4     12/ \   /   \2  5 8   16 输出:   6/ ...

  5. IT公司100题-9-判断整数序列是不是二元查找树的后序遍历结果

    问题描述: 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回true,否则返回false. 例如输入4, 8, 6, 12, 16, 14, 10,由于这一整数序列是如下树 ...

  6. 6.二元查找树的后序遍历结果[PostOrderOfBST]

    [题目] 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回true,否则返回false. 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果: 8 ...

  7. 11.求二元查找树的镜像[MirrorOfBST]

    [题目] 输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于右子树的结点.用递归和循环两种方法完成树的镜像转换. 例如输入: 8    /  \  6      1 ...

  8. 数据结构:JAVA_二叉数查找树基本实现(上)

    数据结构:二叉数查找树基本实现(JAVA语言版) 1.写在前面 二叉查找树是一种能将链表插入的灵活性与有序数组查找的高效性结合在一起的一种数据结构. ..... 2.代码分解 2.1 对节点的结构定义 ...

  9. 【查找结构5】多路查找树/B~树/B+树

    在前面专题中讲的BST.AVL.RBT都是典型的二叉查找树结构,其查找的时间复杂度与树高相关.那么降低树高自然对查找效率是有所帮助的.另外还有一个比较实际的问题:就是大量数据存储中,实现查询这样一个实 ...

随机推荐

  1. Requirejs加载超时问题的一个解决方法:设置waitSeconds=0

    有时Requirejs会遇到加载js超时问题 除了排查js脚本问题,网络问题以外的一个解决方法是加大Require的等待时间waitSeconds,或者直接设置为0,这个参数的意义是:The numb ...

  2. Windows XP 中设置VPN(PPTP连接方式)

    第一步:点开始-网上邻居或者控制面板-网络连接,选择-创建一个新的连接 第二步:点击-下一步 第三步:选择-连接到我的工作场所的网络,点击-下一步 第四步:选择-虚拟专用网络连接,点击-下一步 第五步 ...

  3. mysql 关键字 字段 转义

    insert into tb_gps(imei,lat,lon,speed,dir,alt,atom,`signal`,batt,intime) values('46345435435345','22 ...

  4. 每日英语:A Whiff Of 'Welcome Home'

    Buying real estate involves weighing a lot of factors: location, price . . . smell? Some condo devel ...

  5. 【转帖】自助式BI的崛起:三张图看清商业智能和大数据分析市场趋势

    自助式BI的崛起:三张图看清商业智能和大数据分析市场趋势 大数据时代,商业智能和数据分析软件市场正在经历一场巨变,那些强调易用性的,人人都能使用的分析软件正在取代传统复杂的商业智能和分析软件成为市场的 ...

  6. viewpager的简单使用,以及ValueAnimator的用法示例

    之前在网上看到一篇viewpager简单使用的例子程序,主要采用了上部标签button+中间指示作用的imageview+下部viewpager的结构,点击上部标签,或者滑动viewpager,均可以 ...

  7. C++ STL轻松导学

    作为C++标准不可缺少的一部分,STL应该是渗透在C++程序的角角落落里的.STL不是实验室里的宠儿,也不是程序员桌上的摆设,她的激动人心并非昙花一现.本教程旨在传播和普及STL的基础知识,若能借此机 ...

  8. Spring源码追踪2——xml解析入口

    解析xml节点入口 org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDe ...

  9. TokuDB调研文档

    另见链接:http://note.youdao.com/share/?id=77dd1e9cc139b57586665f702467c56a&type=note   安装 安装主要包括两种方法 ...

  10. EDM博主笔记:EDM邮件营销的几个细节问题

    其实说起EDM邮件营销很多做过的人都知道,目前国内邮件营销的效果其实是比较差的,为什么?因为国内没有多少使用邮件的习惯,如果不是工作所需估计很多的人都几天不碰邮件了,但是反观国外 邮件是其日常的一部分 ...