* 面试题36:二叉搜索树与双向链表 自己重新键入了一遍的
* 题目:输入一棵二叉搜索树,将该二叉搜索树转换为一个排序的双向链表
* 要求不能创建任何新的节点,只能调整树中节点指针的指向。
* 例如:输入10 -> (left)6 10 -> (right)14这棵二叉搜索树,
* 6 -> (left)4 6 -> (right)8
* 14 -> (left)12 14 -> (right)16
* 则输出转换之后的排序双向链表: 4<-->6<-->8<-->10<-->12<-->14<-->16
*
*
* 思路: 递归思想, 首先找到左子树的最后一个节点,
* 第一步:(<--操作)将根节点的左指针指向最后一个节点
* 第二步:(-->操作)将最后一个节点的右指针指向根节点
* 第三步:(下移操作)最后将根节点赋值为双向循环链表的最后一个节点(完成后移)
* 再次将最后一个节点传过去,然后完成上诉三步,在返回最后一个节点
* 返回最后一个节点后,要将指针重新指向根节点 使用while循环完成即可。
package Test;
import Test.No27BinaryTreeMirror.BinaryTreeNode;
public class No36Copy_No36BinarySearchTreeConvertDouList {
/*
* 面试题36:二叉搜索树与双向链表 自己重新键入了一遍的
* 题目:输入一棵二叉搜索树,将该二叉搜索树转换为一个排序的双向链表
* 要求不能创建任何新的节点,只能调整树中节点指针的指向。
* 例如:输入10 -> (left)6 10 -> (right)14这棵二叉搜索树,
* 6 -> (left)4 6 -> (right)8
* 14 -> (left)12 14 -> (right)16
* 则输出转换之后的排序双向链表: 4<-->6<-->8<-->10<-->12<-->14<-->16
*
*
* 思路: 递归思想, 首先找到左子树的最后一个节点,
* 第一步:(<--操作)将根节点的左指针指向最后一个节点
* 第二步:(-->操作)将最后一个节点的右指针指向根节点
* 第三步:(下移操作)最后将根节点赋值为双向循环链表的最后一个节点(完成后移)
* 再次将最后一个节点传过去,然后完成上诉三步,在返回最后一个节点
* 返回最后一个节点后,要将指针重新指向根节点 使用while循环完成即可。
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
No36Copy_No36BinarySearchTreeConvertDouList b = new No36Copy_No36BinarySearchTreeConvertDouList();
BinaryTreeNode root1 = new BinaryTreeNode(10);
BinaryTreeNode one = new BinaryTreeNode(6);
BinaryTreeNode two = new BinaryTreeNode(14);
BinaryTreeNode three = new BinaryTreeNode(4);
BinaryTreeNode four = new BinaryTreeNode(8);
BinaryTreeNode five = new BinaryTreeNode(12);
BinaryTreeNode six = new BinaryTreeNode(16);
root1.left = one;
root1.right = two;
one.left = three;
one.right = four;
two.left = five;
two.right = six;
three.left = null;
three.right = null;
four.left = null;
four.right = null;
five.left = null;
five.right = null;
six.left = null;
six.right = null;
System.out.println("二叉搜索树转换为双向链表的结果为:");
BinaryTreeNode result = b.Convert(root1);
for(int i = 0;i < 7;i ++) {
System.out.println("输出第"+i+"个节点:"+result.val);
result = result.right;
}
}
//转换为双向链表
public BinaryTreeNode Convert(BinaryTreeNode root) {
// TODO Auto-generated method tub
BinaryTreeNode lastNode = null;
BinaryTreeNode headNode = ConvertNode(root,lastNode);
//headNode 获取到双向链表的最后一个节点
while(headNode != null && headNode.left != null) {
headNode = headNode.left;
}
return headNode;
}
//转换节点
public BinaryTreeNode ConvertNode(BinaryTreeNode rootNode, BinaryTreeNode lastNode) {
// TODO Auto-generated method stub
if(rootNode == null) {
return null;
}
//处理左子树 在左子树中找到最后一个节点
while(rootNode.left != null) {
lastNode = ConvertNode(rootNode.left,lastNode);
}
//(完成<--连接)找到最后一个节点之后 根节点的左指针 赋值为 找到的最后一个节点
rootNode.left = lastNode;
//(完成-->连接)若最后一个节点不为空 则将其右节点指向 根节点
if(lastNode != null) {
lastNode.right = rootNode;
}
//(完成向后移动的操作----最后一个节点赋值为根节点 )将根节点赋值为最后一个节点
rootNode = lastNode;
//处理右子树
while(rootNode.right != null) {
lastNode = ConvertNode(rootNode.right,lastNode);
}
//返回双向链表的最后一个节点
return lastNode;
}
}
* 面试题37:序列化、反序列化二叉树
* 题目:请实现两个函数,分别用来序列化和反序列化二叉树
*
* 序列化:一棵二叉树按照某种遍历方式的结果一某种格式保存为字符串,从而可使内存中建立起来的二叉树持久保存
* 反序列化:根据某种遍历顺序得到的序列化字符串结果,重新构建(重构)二叉树
*
* 思路:
* 序列化:通过先序遍历二叉树的方式进行序列化
* 反序列化 根据序列化的结果进行反序列化,重构二叉树
* 对其进行分割使用split,然后使用一个全局常量index定位索引的节点
* 若不为空,(表示节点不是$)创建创新的二叉树结点,将其存入(根节点存入)
* 然后根据先序遍历的思想---根左右节点进行遍历
* 再判断其左节点和右节点 继续 若不为空就将其创建新节点。。. 重复上边步骤
* 若为空,则直接返回node(初始值定为null)
package Test;
import Test.No27BinaryTreeMirror.BinaryTreeNode;
public class No37Deserialize {
/*
* 面试题37:序列化二叉树
* 题目:请实现两个函数,分别用来序列化和反序列化二叉树
*
* 序列化:一棵二叉树按照某种遍历方式的结果一某种格式保存为字符串,从而可使内存中建立起来的二叉树持久保存
* 反序列化:根据某种遍历顺序得到的序列化字符串结果,重新构建(重构)二叉树
*
* 思路:
* 序列化:通过先序遍历二叉树的方式进行序列化
* 反序列化 根据序列化的结果进行反序列化,重构二叉树
* 对其进行分割使用split,然后使用一个全局常量index定位索引的节点
* 若不为空,(表示节点不是$)创建创新的二叉树结点,将其存入(根节点存入)
* 然后根据先序遍历的思想---根左右节点进行遍历
* 再判断其左节点和右节点 继续 若不为空就将其创建新节点。。. 重复上边步骤
* 若为空,则直接返回node(初始值定为null)
*
*
* */
static class BinaryTreeNode{
int val;
BinaryTreeNode left;
BinaryTreeNode right;
BinaryTreeNode(int val){
this.val = val;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
No37Deserialize d = new No37Deserialize();
BinaryTreeNode root1 = new BinaryTreeNode(8);
BinaryTreeNode one = new BinaryTreeNode(8);
BinaryTreeNode two = new BinaryTreeNode(7);
BinaryTreeNode three = new BinaryTreeNode(9);
BinaryTreeNode four = new BinaryTreeNode(2);
BinaryTreeNode five = new BinaryTreeNode(4);
BinaryTreeNode six = new BinaryTreeNode(7);
// String d1 = "aa$bbb$cc";
// String[] sd = d1.split("\\$");
// for(int i = 0; i < sd.length;i++) {
// System.out.println(sd[i]);
//
// }
// System.out.println("输出源字符串:"+d1);
// 仍旧是源字符串 split过后
root1.left = one;
root1.right = two;
one.left = three;
one.right = four;
two.left = null;
two.right = null;
three.left = null;
three.right = null;
four.left = five;
four.right = six;
five.left = null;
five.right = null;
six.left = null;
six.right = null;
String s = new String();
//序列化二叉树
s = d.Serialize(root1);
System.out.println("用先序遍历的方式序列化二叉树,输出序列结果:"+s);
//反序列化二叉树
BinaryTreeNode root = d.Deserialize(s);
System.out.println("反序列化二叉树后,以先序遍历的方式输出二叉树:");
if(root != null) {
PrintBinaryTree(root);
//未通过b调用PrintBinaryTree()函数,所以该函数要设置为static形式
}
}
//使用先序遍历过程序列化二叉树
private String Serialize(BinaryTreeNode root) {
// TODO Auto-generated method stub
StringBuffer sb = new StringBuffer();
if(root == null) {
sb.append("$,");
return sb.toString();
}
sb.append(root.val + ",");
//先序遍历二叉树 根 左右
sb.append(Serialize(root.left));
sb.append(Serialize(root.right));
return sb.toString();
}
//索引记录 遍历到第几个节点
int index = -1;
//反序列化 将序列化后的 在进行反序列化 转换为原来的二叉树
public BinaryTreeNode Deserialize(String s) {
int length = s.length();
String[] str = s.split(",");
//分割 分割S字符串,并且将分割后的字符串数组赋值给str
//welcome - to - Beijing
//分割为 str[0]:welcome str[1]:to str[2]:Beijing
return DeserializeNode(str,length);
}
public BinaryTreeNode DeserializeNode(String[] str,int length) {
// TODO Auto-generated method stub
index ++; //索引值
BinaryTreeNode node = null;
if(index >= length) {
return null;
}
//若str[index]不为$ 表示此节点不为空
// 则进行构建新的节点 以及查看他的左右子节点
if(!str[index].equals("$")) {
node = new BinaryTreeNode(Integer.valueOf(str[index]));
//index一直再增加 所以node取得的值也一直在变化 str[0],str[1],str[2],...
node.left = DeserializeNode(str,length);
node.right = DeserializeNode(str,length);
}
//若几点为$ 此节点为空指针 则直接返回 node即可
//(因为定义时 node定义为空,因此不必再次对其进行赋空指针)
//返回二叉树的一个节点
return node;
}
//输出二叉树节点值 根左右(先序遍历二叉树)
public static void PrintBinaryTree(BinaryTreeNode root1) {
System.out.println(root1.val);
if(root1.left == null && root1.right == null) {
return;
}
if(root1.left != null) {
PrintBinaryTree(root1.left);
}
if(root1.right != null) {
PrintBinaryTree(root1.right);
}
}
}