剑指Offer面试题(第二十二天)面试题36、37

 * 面试题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);
		}			
	}

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值