二元查找树转变成排序的双向链表之C#算法实现
此题为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之间的关系。
算法思路:
- 树根节点,分左右子树。先将当前节点左子树范围内最右节点leftR找出来,再将右子树范围内最左节点rightL找出来(这两步放在一开始,因为此时左右子树内的关系还没改变,先取出来,时间消耗O(lgN)。只是查找到节点,空间上只用到一个索引,不会产生新的内存分配)。
- 若左子树为叶子节点,则直接设置其右向索引指向其父节点,左向递归结束;否则,将此节点作为根节点,递归调用第一步。
- 若右子树为叶子节点,则直接设置其左向索引指向其父节点,右向递归结束,否则,将此节点作为根节点,递归调用第一步。
- 设置根节点的左向节点为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#算法实现的更多相关文章
- MS - 1 - 把二元查找树转变成排序的双向链表
## 1. 把二元查找树转变成排序的双向链表 ## ### 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表. ### 要求不能创建任何新的结点,只调整指针的指向. 10 ...
- 【Data structure & Algorithm】把二元查找树转变成排序的双向链表
把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表,要求不能创建任何新节点,只调整指针指向. 比如将二元查找树 10 / \ 6 ...
- 1.把二元查找树转变成排序的双向链表[BST2DoubleLinkedList]
[题目]:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向. 比如将二元查找树 . 10 / \ 6 14 / \ / \ 4 8 12 16 转 ...
- IT公司100题-15-求二元查找树的镜像
问题描述: 输入一颗二元查找树,将该树转换为它的镜像树,即对每一个节点,互换左右子树. 例如输入: 6/ \4 12/ \ / \2 5 8 16 输出: 6/ ...
- IT公司100题-9-判断整数序列是不是二元查找树的后序遍历结果
问题描述: 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回true,否则返回false. 例如输入4, 8, 6, 12, 16, 14, 10,由于这一整数序列是如下树 ...
- 6.二元查找树的后序遍历结果[PostOrderOfBST]
[题目] 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回true,否则返回false. 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果: 8 ...
- 11.求二元查找树的镜像[MirrorOfBST]
[题目] 输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于右子树的结点.用递归和循环两种方法完成树的镜像转换. 例如输入: 8 / \ 6 1 ...
- 数据结构:JAVA_二叉数查找树基本实现(上)
数据结构:二叉数查找树基本实现(JAVA语言版) 1.写在前面 二叉查找树是一种能将链表插入的灵活性与有序数组查找的高效性结合在一起的一种数据结构. ..... 2.代码分解 2.1 对节点的结构定义 ...
- 【查找结构5】多路查找树/B~树/B+树
在前面专题中讲的BST.AVL.RBT都是典型的二叉查找树结构,其查找的时间复杂度与树高相关.那么降低树高自然对查找效率是有所帮助的.另外还有一个比较实际的问题:就是大量数据存储中,实现查询这样一个实 ...
随机推荐
- 如何通过Socket TCP发送并接收一个文件?
一.小结 1.大包发小包收,只发一次. 2.发时把文件扩展名,文件长度也随同一起发送,方便接收端接收时另存为正确的文件类型,并判断是否已经接收完毕. 如果不一起发送,分为文件扩展名,文件长度,文件内容 ...
- Base: 一种 Acid 的替代方案
原文链接: BASE: An Acid Alternative Pdf下载链接: Base 数据库 ACID,都不陌生:原子性.一致性.隔离性和持久性,这在单台服务器就能搞定的时代,很容易实现,但是到 ...
- [转] IE6中请求莫名中断
这两天碰到的问题,IE6下某个js生成的a节点,设置了href="javascript:;",点击时触一个ajax请求,但在IE6下就是无法执行succese里的内容,所以就用se ...
- jqPlot插件绘制柱状图
每天都在这里看别人写的东西,确发现自己好久没写文章了,可能是因为确实很忙,或许这也是在给自己找的一种借口. 不过这也是我人生中加入得第一个创业公司,来到这里才知道创业公司其实真的很辛苦,产品的萌芽才开 ...
- Openvswitch原理与代码分析(2): ovs-vswitchd的启动
ovs-vswitchd.c的main函数最终会进入一个while循环,在这个无限循环中,里面最重要的两个函数是bridge_run()和netdev_run(). Openvswitch主要 ...
- CSS3实现旋转的太极图(二):只用1个DIV
效果预览: PS: 1.昨天用3个DIV实现了太极图(点击查看),,今天试着用1个Div来做. 2.公司刚忙过双10周年庆,最近空闲下来,闲着也是闲着,总得写点东西吧. 3.高手莫喷,小弟仅仅是没 ...
- 查询反模式 - GroupBy、HAVING的理解
为了最简单地说明问题,我特地设计了一张这样的表. 一.GROUP BY单值规则 规则1:单值规则,跟在SELECT后面的列表,对于每个分组来说,必须返回且仅仅返回一个值. 典型的表现就是跟在SELEC ...
- MFC中混合使用Duilib制作界面
因为公司项目最近入了MFC的这个大坑,用MFC做UI做了一段时间,感觉不是很方便,开发效率有点慢. 看了c++里面做界面的类库,感觉Duilib比较符合做界面的需求,而且很多大公司也在使用Duilib ...
- 参照nopCommerce框架开发(NextCMS)
很久没有更新博客了,现在已经不写.NET,转前端半年多了. 半年前在创业公司,做电子商务网站,用的是NopCommerce框架(3.2),这个框架还是相当不错的,经过一段时间的摸索,基本入门,于是就开 ...
- Git 执行 「fork 出来的仓库」和「最新版本的原仓库」内容同步更新
当我们在 GitHub 上 fork 出一个仓库后,如果原仓库更新了,此时怎样才能保证我们 fork 出来的仓库和原仓库内容一致呢?我们一般关注的是仓库的 master(主干分支)的内容,通过以下步骤 ...