微软算法100题01 二叉搜索树转为双向链表

提高编程能力的最佳途径就是多写代码, 就让我们从现在开始吧!

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

二叉查找树的特点:任意节点的左子树都要小于当前节点;右子树都要大于当前节点。
特点:查询某个值,需要的时间复杂度为O(lgN)

网上的解决方案大部分都是C的, 我给出一个JAVA的吧

我的思路:  如果要把一颗二叉树转换为已排序的双向链表,则在双向链表中,根节点的左子树必然在根节点的前面,根节点的右子树必然在根节点的后面,根节点的直接前缀节点必然为左子树中最大的节点根节点的直接后缀节点必然为右子树中最小的节点

1. 找到根节点的左子树,找到其最大节点,作为根节点的前缀节点

2. 找到根节点的右子树,找到其最小节点,作为根节点的后缀节点

3.如果左子树不是叶子节点,则用1和2 的逻辑递归处理该左子树

4.如果右子树不是叶子节点,则用1和2 的逻辑递归处理该右子树

  1 package com.rui.microsoft;
  2
  3 /**
  4  *
  5  *
  6  * 把二元查找树转变成排序的双向链表
  7 题目:
  8 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
  9 要求不能创建任何新的结点,只调整指针的指向。
 10 10
 11 /  12 5  15
 13 / \ /  14 3 6 13 16
 15 转换成双向链表
 16 3=5=6=10=13=15=16
 17  */
 18 public class Test01 {
 19
 20     public static void main(String[] args) {
 21         Test01 test = new Test01();
 22         Node root = test.initTree();
 23         Node head = test.convertToDoubleLink(root);
 24         while(null != head){
 25             System.out.print(" " + head.getValue());
 26             head = head.getRight();
 27         }
 28     }
 29
 30     private boolean isLeaf(Node node){
 31         if(null == node.getLeft() && null == node.getRight()) return true;
 32         else return false;
 33     }
 34
 35     private Node findMin(Node node){
 36         if(null == node) return null;
 37         if(null == node.getLeft()) return node;
 38         return findMin(node.getLeft());
 39     }
 40
 41     private Node findMax(Node node){
 42         if(null == node) return null;
 43         if(null == node.getRight()) return node;
 44         return findMin(node.getRight());
 45     }
 46
 47     public Node convertToDoubleLink(Node node){
 48         if(null == node) return null;
 49
 50         Node head = findMin(node);
 51
 52         //Find the node directly before current node in the double link
 53         Node leftNode = findMax(node.getLeft());
 54
 55         //Find the node directly after current node in the double link
 56         Node rightNode = findMin(node.getRight());
 57
 58         //Process left
 59         if(null != node.getLeft()){
 60             processLeftTree(node.getLeft(), node);
 61         }
 62
 63         //Process right
 64         if(null != node.getRight()){
 65             processRightTree(node.getRight(), node);
 66         }
 67
 68         //Relocate leftNode according to double link to the left side of current node
 69         if(null != leftNode){
 70             leftNode.setRight(node);
 71             node.setLeft(leftNode);
 72         }
 73
 74         //Relocate rightNode according to double link to the right side of current node
 75         if(null != rightNode){
 76             rightNode.setLeft(node);
 77             node.setRight(rightNode);
 78         }
 79
 80         return head;
 81     }
 82
 83     private void processRightTree(Node right, Node node) {
 84         if(isLeaf(right)){
 85             right.setLeft(node);
 86             return;
 87         }
 88         convertToDoubleLink(right);
 89     }
 90
 91     private void processLeftTree(Node left, Node node) {
 92         if(isLeaf(left)){
 93             left.setRight(node);
 94             return;
 95         }
 96         convertToDoubleLink(left);
 97     }
 98
 99     private Node initTree(){
100         Node root = new Node();
101         root.setValue(10);
102
103         Node node01 = new Node();
104         node01.setValue(5);
105
106         Node node011 = new Node();
107         node011.setValue(3);
108
109         Node node012 = new Node();
110         node012.setValue(6);
111
112         node01.setLeft(node011);
113         node01.setRight(node012);
114
115         root.setLeft(node01);
116
117         Node node02 = new Node();
118         node02.setValue(15);
119
120         Node node021 = new Node();
121         node021.setValue(13);
122
123         Node node022 = new Node();
124         node022.setValue(16);
125
126         node02.setLeft(node021);
127         node02.setRight(node022);
128
129         root.setRight(node02);
130         return root;
131     }
132
133
134     class Node {
135
136         private int value;
137         private Node left;
138         private Node right;
139
140         /**
141          * @return the value
142          */
143         public int getValue() {
144             return value;
145         }
146         /**
147          * @param value the value to set
148          */
149         public void setValue(int value) {
150             this.value = value;
151         }
152         /**
153          * @return the left
154          */
155         public Node getLeft() {
156             return left;
157         }
158         /**
159          * @param left the left to set
160          */
161         public void setLeft(Node left) {
162             this.left = left;
163         }
164         /**
165          * @return the right
166          */
167         public Node getRight() {
168             return right;
169         }
170         /**
171          * @param right the right to set
172          */
173         public void setRight(Node right) {
174             this.right = right;
175         }
176     }
177 }
时间: 2024-12-17 07:13:52

微软算法100题01 二叉搜索树转为双向链表的相关文章

编程算法 - 二叉搜索树 与 双向链表 代码(C++)

二叉搜索树 与 双向链表 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目:输入一颗二叉搜索树, 将该二叉搜索树转换成一个排序的双向链表. 要求不能创建不论什么新的结点, 仅仅能调整数中结点的指针的指向. 方法: 使用中序遍历每个结点, 并进行连接, 即左子树指前, 右子树指后, 并保存前一个节点. 本程序包括算法原理, 測试程序, 及 输出. /* * main.cpp * * Created on: 2014.6.12 * Author

微软算法100题88 将字符串中的字符'*'移到串的前部分

函数将字符串中的字符'*'移到串的前部分,前面的非'*'字符后移,但不能改变非'*'字符的先后顺序,函数返回串中字符'*'的数量.如原始串为:ab**cd**e*12,处理后为*****abcde12,函数并返回值为5.(要求使用尽量少的时间和辅助空间) 思路:类似于快速排序,用两个指针分别指向字符数组的左右边界,寻找左边第一个不为*的字符,寻找右边第一个*,然后交换字符,然后继续寻找和交换的过程,直到两个指针相交, 时间复杂度o(n), 空间复杂度o(1) 第一个写的程序有问题,没有考虑到保持

二叉搜索树与双向链表的转换

题目:输入一棵二叉搜索树(记住是搜索树),将该二叉搜索树转换为一个排序的双向链表.要求:不能创建任何新的结点,只能调整树中结点指针的指向. 分析:如下图 因为是二叉搜索树.所以树的排列是规则的.通过中序遍历正好遍历的是由小到大的序列. 要求说明是只能改变树结点指针的指向,不能增加新的空间和结点.所以在中序遍历的时候,主要是遍历到结点后就去改变指针指向. 为了简单,采用递归进行遍历. 树的结构 struct BinaryTreeNode{ int m_data; BinaryTreeNode* m

24.二叉搜索树与双向链表

二叉搜索树与双向链表 参与人数:2316时间限制:1秒空间限制:32768K 算法知识视频讲解 题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. // 25.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(i

4.二叉搜索树转为有序双向链表(递归算法与非递归算法)

一.题目 要求输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建新的节点,只能调整树中结点指针的指向. 二叉树结点定义如下: 1 struct BinaryTreeNode 2 { 3 int m_nValue; 4 BinaryTreeNode *m_pLeft; 5 BinaryTreeNode *m_pRight; 6 }; 图1.二叉搜索树转为有序双向链表 二.算法 (1)递归算法 因为二叉搜索树每个结点的子树也是一棵二叉搜索树,所以,我们可以把问题分解为, 把左子

剑指OFFER之二叉搜索树与双向链表(九度OJ1503)

题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 输入: 输入可能包含多个测试样例.对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数.接下来的n行,每行为一个二叉搜索树的先序遍历序列,其中左右子树若为空则用0代替. 输出: 对应每个测试案例,输出将二叉搜索树转换成排序的双向链表后,从链表头至链表尾的遍历结果. 样例输入: 1 2 1 0 0 3 0 0 样例输出: 1 2 3 解题思路

二叉搜索树与双向链表-剑指Offer

二叉搜索树与双向链表 题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路 按中序遍历二叉搜索树可从小到大遍历元素 边遍历元素边创建双向链表 最后得到的双向链表的指针指向最后一个节点,所以需要再往回遍历一遍让指针指到头结点 代码 /** public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public Tre

二叉搜索树与双向链表——27

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,要求不能创建任何新的结点,只能调整树中结点指针的指向. 如上所示的二叉搜索树,转换成排序的双向链表就是5-><-6-><-7-><-8-><-9-><-10-><-11. 因为要求转换成双向链表,而恰好二叉树的每个结点都有两个指针,因此可以直接调整指针的指向:对于搜索二叉树,每个结点的左子树的值都比根结点的值要小,而每个右子树的值都比当前结点的值要大,而要求转换成排序的双向链

剑指offer (27) 二叉搜索树和双向链表

题目:输入一棵BST,将该BST转换成一个排序的双向链表 要求不能创建新的结点,只能调整树中结点指针的指向 在BST中,左子节点的值 小于父节点的之, 父节点的值小于 右子节点的值 因此我们在转换成有序的双向链表时,原先指向左子节点的指针调整为链表中指向前一个结点的指针 原先指向右子节点的指针调整为链表中指向后一个结点的指针 很自然的想到对BST进行中序遍历 当我们遍历转换到根节点(值为10的结点)时,它的左子树已经转换成 一个排序的链表了,并且处在链表中的最后一个结点是当前值最大的结点 我们把