剑指Offer之非递归实现二叉树的前,中,后 序以及层次遍历和序列化,反序列化

先序思路:

先将头节点放入栈中,弹出打印,然后判断当前节点的右节点是否为空,不为空,放入栈中,然后再将当前节点的左节点放入栈中,因为放入的顺序是先右再左,利用了栈的特殊性,便实现了二叉树的非递归先序遍历

public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList<Integer>();
        if(root==null){
            return list;
        }
        preOrder(root,list);
        return list;
    }
    public void preOrder(TreeNode root,List<Integer> list){
        if(root==null){
            return ;
        }
        Stack<TreeNode> stack=new Stack<TreeNode>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode pop=stack.pop();
            list.add(pop.val);
            if(pop.right!=null){
                stack.push(pop.right);
            }
            if(pop.left!=null){
                stack.push(pop.left);
            }
        }
    }

中序思路:

递归的实质就是调用栈的过程,不过调用过程不是我们来决定的,那我们就自己实现一个栈来进行遍历,

过程:head指针往下移动,一开始先将二叉树的所有左边界一次性放入栈中,然后直到head指针指向空,将栈中的元素打印,head指针移向打印的节点的右子节点,再进行判断是否有左边界,有全部放入栈中,若没有,则打印。循环此步骤。

//定义节点
public  static class Node {
	    int val = 0;
	    Node left = null;
	    Node right = null;

	    public Node(int val) {
	        this.val = val;

	    }

}
public static void inOrder(Node head) {
    	 if(head!=null) {
    		 Stack<Node> stack=new Stack<Node>();
    		 while(head!=null ||!stack.isEmpty()) {
    			 if(head!=null) {
    				 stack.push(head);
    				 head=head.left;
    			 }else {
    				 head = stack.pop();
    				 System.out.println(head.val);
    				 head=head.right;
    			 }
    		 }
    	 }
 }

后序遍历

使用二个栈,一个先实现根右左,再利用另外一个栈实现反转得到左右根即二叉树的后序遍历

//后序遍历,非递归
	public static List<Integer> postOrder2(TreeNode head) {
		Stack<TreeNode> stack1=new Stack<TreeNode>();
		Stack<TreeNode> stack2=new Stack<TreeNode>();
		List<Integer> list=new ArrayList<Integer>();
	
		stack1.add(head);
		while(!stack1.isEmpty()) {
			head = stack1.pop();
			//System.out.println(head.val);
			stack2.push(head);
			if(head.left!=null) {
				stack1.add(head.left);
			}
			if(head.right!=null) {
				stack1.add(head.right);
			}
		}
		while(!stack2.isEmpty()) {
			list.add(stack2.pop().val);
		}
		return list;

	}

层次遍历

思路:准备一个队列,一开始先将头节点放入队列,弹出打印,如果左节点不为空,将左节点放入,如果右节点不为空,放入右节点

public static void printByLevel(Node head) {
		if(head==null) {
			System.out.println(head);
		}
		Queue<Node> queue=new LinkedList<Node>();
		queue.offer(head);
		while(!queue.isEmpty()) {
			head=queue.poll();
			System.out.print(head.value+" ");
			if(head.left!=null) {
				queue.offer(head.left);
			}
			if(head.right!=null) {
				queue.offer(head.right);
			}
		}
	}

先序的序列化与反序列化

//先序序列化二叉树
	public static String process(Node head) {
		if(head==null) {
			return "#_";
		}
		String res=head.value+"_";
		res+=process(head.left);
		res+=process(head.right);
		return res;
	}
	//反序列化
	public static Node recover(String str) {
		String[] split = str.split("_");
		Queue<String> queue=new LinkedList<String>();
		
		for(int i=0;i<split.length;i++) {
			queue.add(split[i]);
		}
		
		return reconProOrder(queue);
	}
	public static Node reconProOrder(Queue <String> queue) {
		String value=queue.poll();
		if(value.equals("#")) {
			return null;
		}
		Node head=new Node(Integer.valueOf(value));
		head.left=reconProOrder(queue);
		head.right=reconProOrder(queue);
		return head;
	}

按层序列化与反序列化:
序列化,在进行将左右节点放入队列的时候判断,如果为空连接空表示的字符串,不为空连接不为空的字符串

public static String serialByLevel(Node head) {
		if (head == null) {
			return "#!";
		}
		String res = head.value + "!";
		Queue<Node> queue = new LinkedList<Node>();
		queue.offer(head);
		while (!queue.isEmpty()) {
			head = queue.poll();
			if (head.left != null) {
				res += head.left.value + "!";
				queue.offer(head.left);
			} else {
				res += "#!";
			}
			if (head.right != null) {
				res += head.right.value + "!";
				queue.offer(head.right);
			} else {
				res += "#!";
			}
		}
		return res;
	}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值