剑指offer系列之二十五:二叉搜索树与双向链表
2015-12-09 15:07
453 查看
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
由于二叉搜索树的中序遍历就是排序的,如果是构造单链表,只需要一次中序遍历就可以了,但现在需要构造双链表,也就是在中序遍历的过程中需要设置每个节点的left与right指针,现在问题是如何设置这两个指针?二叉搜索树有一个特点,就是根节点的左子树上所有节点都比根节点的值小,而右子树上的所有节点的值都比根节点的值大,利用这个性质,当遍历根节点的左孩子的时候,可以继续把其当做左子树的根节点,右孩子可以当做右子树的根节点,从而使用递归完成。
以左子树为例,依次访问节点的左孩子,当遍历到叶子节点的时候,递归结束,并把该叶子节点设为左子树转换的双链表的第一个节点,然后把其父节点链在其右边,设置left和right指针;如果父节点有右孩子,则继续对其右孩子继续转换,链在父节点的右边(父节点的右孩子肯定比父节点大)。这样当左右子树都转换完成后,返回双链表的第一个节点就可以了。
下面是基于这种思路的Java代码(已被牛客AC):
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
由于二叉搜索树的中序遍历就是排序的,如果是构造单链表,只需要一次中序遍历就可以了,但现在需要构造双链表,也就是在中序遍历的过程中需要设置每个节点的left与right指针,现在问题是如何设置这两个指针?二叉搜索树有一个特点,就是根节点的左子树上所有节点都比根节点的值小,而右子树上的所有节点的值都比根节点的值大,利用这个性质,当遍历根节点的左孩子的时候,可以继续把其当做左子树的根节点,右孩子可以当做右子树的根节点,从而使用递归完成。
以左子树为例,依次访问节点的左孩子,当遍历到叶子节点的时候,递归结束,并把该叶子节点设为左子树转换的双链表的第一个节点,然后把其父节点链在其右边,设置left和right指针;如果父节点有右孩子,则继续对其右孩子继续转换,链在父节点的右边(父节点的右孩子肯定比父节点大)。这样当左右子树都转换完成后,返回双链表的第一个节点就可以了。
下面是基于这种思路的Java代码(已被牛客AC):
package com.rhwayfun.offer; public class ConvertTreeToDLinkedList { static class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } public TreeNode Convert(TreeNode pRootOfTree) { if(pRootOfTree == null) return null; if(pRootOfTree.left == null && pRootOfTree.right == null) return pRootOfTree; TreeNode pLastNodeOfLeftList = Convert(pRootOfTree.left); TreeNode p = pLastNodeOfLeftList; //定位到左子树双链表的最后一个节点 while(p != null && p.right != null){ p = p.right; } //将root节点追加到左子树双链表的最后一个节点 if(pLastNodeOfLeftList != null){ p.right = pRootOfTree; pRootOfTree.left = p; } //转换右子树为双链表 TreeNode pLastNodeOfRightList = Convert(pRootOfTree.right);; //将root追加至右子树双链表的最后一个节点 if(pLastNodeOfRightList != null){ pLastNodeOfRightList.left = pRootOfTree; pRootOfTree.right = pLastNodeOfRightList; } //返回左子树的第一个节点 if(pLastNodeOfLeftList != null) return pLastNodeOfLeftList; return pRootOfTree; } public static void main(String[] args) { TreeNode pRootOfTree = new TreeNode(10); TreeNode node1 = new TreeNode(6); TreeNode node2 = new TreeNode(14); TreeNode node3 = new TreeNode(4); TreeNode node4 = new TreeNode(8); TreeNode node5 = new TreeNode(12); TreeNode node6 = new TreeNode(16); pRootOfTree.left = node1; pRootOfTree.right = node2; node1.left = node3; node1.right = node4; node2.left = node5; node2.right = node6; TreeNode node = new ConvertTreeToDLinkedList().Convert(pRootOfTree); while(node != null){ System.out.print(node.val + " "); node = node.right; } } }
相关文章推荐
- 禁止button提交但是不禁止js提交
- css3学习笔记(二)
- 学习笔记代码,js 之构造函数
- butternife Zelezny自动注入插件
- butternife Zelezny自动注入插件
- butternife Zelezny自动注入插件
- jquery datatable刷新请求方式
- 剑指offer系列之二十四:复杂链表的复制
- css样式大全
- jquery ajax避免重复触发同一个事件
- 移动前端开发之viewport的深入理解
- 剑指offer系列之二十三:二叉树中和为某一值得所有路径
- Myeclipse里导入jQuery.js 时出现错误打红叉的解决方法
- osg::readNodeFile() 异常std::bab_alloc
- [ERR] Not all 16384 slots are covered by nodes.
- 利用 CSS3 判断手机是横屏还是竖屏
- perfect-scrollbar 和 fastclick 整合后首次需要点击两次的处理
- angularjs, nodejs, express, gulp, karma, jasmine 前端方案整合
- CSS-tips
- fastjson排序问题-如何改变fastjson的排序规则