左神b站视频p5 二叉树部分

  1. 实现二叉树的先序、中序、后序遍历,包括递归方式和非递归方式
import java.util.Stack;
public class BinaryTree {
	public static class Tree{
		public int val;
		public Tree left;
		public Tree right;
		public Tree(int x){
			this.val = x;
		}
	}
	
	public static void xianxu(Tree root) {
		//递归的方式
		if(root == null)
			return;
		System.out.println(root.val);
		xianxu(root.left);
		xianxu(root.right);
	}
	public static void xianxu1(Tree root) {
		//先序,非递归的方式
		if(root == null)
			return;
		Stack<Tree> st = new Stack<>();
		st.push(root);
		while(!st.isEmpty()) {
			root = st.pop();
			System.out.println(root.val);
			if(root.right != null) {
				st.push(root.right);
			}
			if(root.left != null){
				st.push(root.left);
			}
		}
	}
	
	public static void zhongxu(Tree root) {
		if(root ==  null)
			return;
		zhongxu(root.left);
		System.out.println(root.val);
		zhongxu(root.right);
	}
	
	public static void zhongxu1(Tree root) {
		//使用非递归的方式实现
		Stack<Tree> st = new Stack<>();

		while(!st.isEmpty() || root != null) {
			if(root != null) {
				st.push(root);
				root = root.left;
			}else {
				root = st.pop();
				System.out.println(root.val);
				root = root.right;
			}
		}
	}
	
	public static void houxu(Tree root) {
		if(root == null)
			return;
		houxu(root.left);
		houxu(root.right);
		System.out.println(root.val);
	}
	
	public static void houxu1(Tree root) {
		if(root == null)
			return;
		//根右左 倒序 左右根
		Stack<Tree> s1 = new Stack<>();
		Stack<Tree> s2 = new Stack<>();
		s1.push(root);
		while(!s1.isEmpty()) {
			root = s1.pop();
			s2.push(root);
			if(root.left != null) {
				s1.push(root.left);
			}
			if(root.right != null) {
				s1.push(root.right);
			}
		}
		while(!s2.isEmpty()) {
			System.out.println(s2.pop().val);
		}
	}
	
	public static void main(String[] args) {
		Tree head = new Tree(5);
		head.left = new Tree(3);
		head.right = new Tree(8);
		head.left.left = new Tree(2);
		head.left.right = new Tree(4);
		head.left.left.left = new Tree(1);
		head.right.left = new Tree(7);
		head.right.left.left = new Tree(6);
		head.right.right = new Tree(10);
		head.right.right.left = new Tree(9);
		head.right.right.right = new Tree(11);

		// recursive
		System.out.println("==============recursive==============");
		System.out.print("pre-order: ");
		xianxu(head);
		System.out.println();
		System.out.print("in-order: ");
		zhongxu(head);
		System.out.println();
		System.out.print("pos-order: ");
		houxu(head);
		System.out.println();

		// unrecursive
		System.out.println("============unrecursive=============");
		xianxu1(head);
		zhongxu1(head);
		houxu1(head);
		//posOrderUnRecur2(head);

	}

}

在这里插入图片描述

/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode.right != null){
            pNode = pNode.right;
            while(pNode.left != null){
                pNode = pNode.left;
            }
            return pNode;
        }else{
            TreeLinkNode x = pNode.next;
            while(x != null){
                if(x.left == pNode)
                    return x;
                pNode = x;
                x = pNode.next;
            }
            return null;
        }
    }
}

在这里插入图片描述
这里使用了先序遍历的序列化和反序列化(递归),以及宽度优先遍历的序列化和反序列化(非递归)。递归二叉树能够回到一个二叉树的结点三次。

//package class_04;

import java.util.LinkedList;
import java.util.Queue;

public class TreeSerialization {

	public static class Node {
		public int value;
		public Node left;
		public Node right;

		public Node(int data) {
			this.value = data;
		}
	}

	public static String serialByLevel(Node head) {
		//用递归不能做出来,被递归的思路限制了,看了代码才知道是用非递归方法
		if(head == null)
			return "#!";
		Queue<Node> qq = new LinkedList<>();
		qq.add(head);
		String res = head.value + "!";
		while(!qq.isEmpty()) {
			head =  qq.poll();
			if(head.left != null) {
				qq.add(head.left);
				res = res + head.left.value + "!";
			}else {
				res += "#!";
			}
			if(head.right != null) {
				qq.add(head.right);
				res = res + head.right.value + "!";
			}else {
				res += "#!";
			}
		}
		return res;
	}
	 
	
	public static String serialByPre(Node head) {
        //先序遍历
        if(head == null){
            return "#!";
        }
        String res = head.value + "!";
        res = res + serialByPre(head.left);
        res = res + serialByPre(head.right);
        return res;
	}
	public static int id = 0;
	public static Node reconByPreString(String preStr) {
		id = 0;
		String[] strarray = preStr.split("!");
	       Node root = new Node(0);
	       return Deserialize(root,strarray);
	}
    public static Node Deserialize(Node root,String[] astr){
        if(id < astr.length){
            if(astr[id].equals("#")){ 
                id++;
               return null;
            }else{
                root = new Node(Integer.valueOf(astr[id++]));
                root.left = Deserialize(root.left,astr);
                root.right = Deserialize(root.right,astr);
                 return root;
            }
        }
            return null;
    }
	public static Node reconPreOrder(Queue<String> queue) {
		String value = queue.poll();
		if (value.equals("#")) {
			return null;
		}
		Node head = new Node(Integer.valueOf(value));
		head.left = reconPreOrder(queue);
		head.right = reconPreOrder(queue);
		return head;
	}



	public static Node reconByLevelString(String levelStr) {
		//非递归方式
		String[] stra = levelStr.split("!");
		if(stra[0].equals("#"))
			return null;
		Node head = new Node(Integer.valueOf(stra[0]));
		Node head1 = head;
		Queue<Node> qq = new LinkedList<>();
		qq.add(head);
		for(int i = 1;i < stra.length;i = i + 2) {
			head = qq.poll();
			if(!stra[i].equals("#")) {
				head.left = new Node(Integer.valueOf(stra[i]));
				qq.add(head.left);
			}
			if(!stra[i+1].equals("#")) {
				head.right = new Node(Integer.valueOf(stra[i+1]));
				qq.add(head.right);
			}
			
		}
		return head1;
	}

	public static Node generateNodeByString(String val) {
		if (val.equals("#")) {
			return null;
		}
		return new Node(Integer.valueOf(val));
	}

	// for test -- print tree
	public static void printTree(Node head) {
		System.out.println("Binary Tree:");
		printInOrder(head, 0, "H", 17);
		System.out.println();
	}

	public static void printInOrder(Node head, int height, String to, int len) {
		if (head == null) {
			return;
		}
		printInOrder(head.right, height + 1, "v", len);
		String val = to + head.value + to;
		int lenM = val.length();
		int lenL = (len - lenM) / 2;
		int lenR = len - lenM - lenL;
		val = getSpace(lenL) + val + getSpace(lenR);
		System.out.println(getSpace(height * len) + val);
		printInOrder(head.left, height + 1, "^", len);
	}

	public static String getSpace(int num) {
		String space = " ";
		StringBuffer buf = new StringBuffer("");
		for (int i = 0; i < num; i++) {
			buf.append(space);
		}
		return buf.toString();
	}

	public static void main(String[] args) {
		Node head = null;
		printTree(head);

		String pre = serialByPre(head);
		System.out.println("serialByPre tree by pre-order: " + pre);
		head = reconByPreString(pre);
		System.out.print("reconstruct tree by pre-order, ");
		printTree(head);

		String level = serialByLevel(head);
		System.out.println("serialByPre tree by level: " + level);
		head = reconByLevelString(level);
		System.out.print("reconstruct tree by level, ");
		printTree(head);

		System.out.println("====================================");

		head = new Node(1);
		printTree(head);

		pre = serialByPre(head);
		System.out.println("serialByPre tree by pre-order: " + pre);
		head = reconByPreString(pre);
		System.out.print("reconstruct tree by pre-order, ");
		printTree(head);

		level = serialByLevel(head);
		System.out.println("serialByPre tree by level: " + level);
		head = reconByLevelString(level);
		System.out.print("reconstruct tree by level, ");
		printTree(head);

		System.out.println("====================================");

		head = new Node(1);
		head.left = new Node(2);
		head.right = new Node(3);
		head.left.left = new Node(4);
		head.right.right = new Node(5);
		printTree(head);

		pre = serialByPre(head);
		System.out.println("serialByPre tree by pre-order: " + pre);
		head = reconByPreString(pre);
		System.out.print("reconstruct tree by pre-order, ");
		printTree(head);

		level = serialByLevel(head);
		System.out.println("serialByPre tree by level: " + level);
		head = reconByLevelString(level);
		System.out.print("reconstruct tree by level, ");
		printTree(head);

		System.out.println("====================================");

		head = new Node(100);
		head.left = new Node(21);
		head.left.left = new Node(37);
		head.right = new Node(-42);
		head.right.left = new Node(0);
		head.right.right = new Node(666);
		printTree(head);

		pre = serialByPre(head);
		System.out.println("serialByPre tree by pre-order: " + pre);
		head = reconByPreString(pre);
		System.out.print("reconstruct tree by pre-order, ");
		printTree(head);

		level = serialByLevel(head);
		System.out.println("serialByPre tree by level: " + level);
		head = reconByLevelString(level);
		System.out.print("reconstruct tree by level, ");
		printTree(head);

		System.out.println("====================================");

	}
}

在这里插入图片描述
**平衡二叉树:对于这棵树的任意节点来说左子树和右子树的高度差超过1。**平衡二叉树不是一颗满二叉树。红黑树在面试中不会让你手写,只会让你说它的概念以及和其他平衡树的区别。
思路:就是任意节点的左子树和右子树的高度之差不大于1.
1.左子树是否平衡,并返回左子树的高度
2.右子树是否平衡,并返回右子树的高度
3.左子树和右子树的高度之差是否大于1


public class BalancedTree {
	//左神b站 P5
	//判断一颗树是否为平衡二叉树
	 public static class TreeNode{
		 public int val;
		 public TreeNode left;
		 public TreeNode right;
		 public TreeNode(int x){
			 this.val = x;
		 }
	 }
	 public static class booint{
		 public boolean is;
		 public int high;
		 public booint(boolean t,int h) {
			 this.is = t;
			 this.high = h;
		 }
	 }
	 public static boolean balancetree(TreeNode root) {
		 if(root == null)
			 return true;
		 return btree(root).is;
	 }
	 //如果需要一个函数返回不同类型的数据 ,像这道题中的boolean,和int,不如创建一个对象。
	public static booint btree(TreeNode root) {
		if(root == null) {
			return new booint(true,0);
		}
		booint left = btree(root.left);
		if(!left.is)
			return new booint(false,0);
		booint right = btree(root.right);
		if(!right.is)
			return new booint(false,0);
		if(Math.abs(left.high - right.high) <= 1)
			return new booint(true,Math.max(left.high, right.high) + 1);
		else 
			return new booint(false,0);
	}
	
	public static void main(String[] args) {
		TreeNode head = new TreeNode(1);
		//head.left = new TreeNode(2);
		head.right = new TreeNode(3);
		//head.left.left = new TreeNode(4);
		//head.left.right = new TreeNode(5);
		head.right.left = new TreeNode(6);
		head.right.right = new TreeNode(7);

		System.out.println(balancetree(head));

	}
}

题目
判断一棵树是否是搜索二叉树、判断一棵树是否是完全二叉树
思路:二叉树中序遍历的节点是依次升序的就是搜索二叉树,通常搜索二叉树中不包含重复结点的。改中序遍历的非递归的代码,打印的时机替换成与前一个节点进行比较

import java.util.Stack;
import java.util.LinkedList;

public class IsSearchTree {
	//判断是否是搜索二叉树
	public static class Node{
		public int val;
		public Node left;
		public Node right;
		public Node(int x) {
			this.val = x;
		}
	}
	public static boolean issearchtree(Node root) {
		if(root == null)
			return true;
		Stack<Node> st = new Stack<>();
		int num = Integer.MIN_VALUE;
		while(!st.isEmpty() || root != null) {
			if(root != null) {
				st.push(root);
				root = root.left;
			}else {
				root = st.pop();
				if(root.val >= num) {//这里和原来中序遍历的地方不一样了
					num = root.val;
				}else
					return false;
				root = root.right;
			}
		}
		return true;
	}
	// for test -- print tree
	public static void printTree(Node head) {
		System.out.println("Binary Tree:");
		printInOrder(head, 0, "H", 17);
		System.out.println();
	}

	public static void printInOrder(Node head, int height, String to, int len) {
		if (head == null) {
			return;
		}
		printInOrder(head.right, height + 1, "v", len);
		String val = to + head.val + to;
		int lenM = val.length();
		int lenL = (len - lenM) / 2;
		int lenR = len - lenM - lenL;
		val = getSpace(lenL) + val + getSpace(lenR);
		System.out.println(getSpace(height * len) + val);
		printInOrder(head.left, height + 1, "^", len);
	}

	public static String getSpace(int num) {
		String space = " ";
		StringBuffer buf = new StringBuffer("");
		for (int i = 0; i < num; i++) {
			buf.append(space);
		}
		return buf.toString();
	}

	public static void main(String[] args) {
		Node head = new Node(4);
		head.left = new Node(2);
		head.right = new Node(6);
		head.left.left = new Node(1);
		head.left.right = new Node(3);
		head.right.left = new Node(5);

		printTree(head);
		System.out.println(issearchtree(head));
		//System.out.println(isCBT(head));

	}
	
}

如何判断完全二叉树?
完全二叉树就是该放的结点都怼在上面,不要跳着怼。完全二叉树和值是没有关系的,结构是完全二叉树
在这里插入图片描述
思路:分三种情况:
宽度优先遍历这棵树

  1. 一个结点有右孩子,没有左孩子,那他肯定不是完全二叉树
  2. 一个结点不是左右两个孩子都全。也就是有左没右或者左右都没有。那么它后面遇到的所有结点都必须是叶节点,否则不是完全二叉树
import java.util.Queue;

//import IsSearchTree.Node;

import java.util.LinkedList;

public class IsAbBinaryTree {
	//判断是否为完全二叉树
	public static class Node{
		public int val;
		public Node left;
		public Node right;
		public Node(int x) {
			this.val = x;
		}
	}

	public static boolean isabbinarytree(Node root) {
		if(root == null)
			return true;
		Queue<Node> qq = new LinkedList<>();
		qq.add(root);
		while(!qq.isEmpty()) {
			root = qq.poll();			
			if(root.right != null && root.left == null) {
				return false;
			}
			if(root.left != null)
				qq.add(root.left);
			if(root.right != null)
				qq.add(root.right);
			if(root.left == null || root.right == null) {
				while(!qq.isEmpty()) {
					root = qq.poll();
					if(!(root.left == null&&root.right == null))
						return false;
				}
				
			}

		}
		return true;
	}
	// for test -- print tree
	public static void printTree(Node head) {
		System.out.println("Binary Tree:");
		printInOrder(head, 0, "H", 17);
		System.out.println();
	}
	public static void printInOrder(Node head, int height, String to, int len) {
		if (head == null) {
			return;
		}
		printInOrder(head.right, height + 1, "v", len);
		String val = to + head.val + to;
		int lenM = val.length();
		int lenL = (len - lenM) / 2;
		int lenR = len - lenM - lenL;
		val = getSpace(lenL) + val + getSpace(lenR);
		System.out.println(getSpace(height * len) + val);
		printInOrder(head.left, height + 1, "^", len);
	}

	public static String getSpace(int num) {
		String space = " ";
		StringBuffer buf = new StringBuffer("");
		for (int i = 0; i < num; i++) {
			buf.append(space);
		}
		return buf.toString();
	}

	public static void main(String[] args) {
		Node head = new Node(4);
		head.left = new Node(2);
		head.right = new Node(6);
		//head.left.left = new Node(1);
		head.left.right = new Node(3);
		head.right.left = new Node(5);

		printTree(head);
		//System.out.println(issearchtree(head));
		System.out.println(isabbinarytree(head));

	}
	
}

用数组实现堆有空间浪费和扩容代价。用二叉树实现堆就不会。
在这里插入图片描述
有一个满二叉树,高度为L,那么它的节点数是2^L - 1;
思路:如果遍历的话时间复杂度就会是O(n)。
遍历左子树的最左节点,找到树的高度。O(logn)
遍历右子树的左边界,如果这里的高度等于树的高度,说明左子树是满的,左子树的高度就求出来了,然后递归去求右子树的节点数。
如果右子树的左边界没到最后一层,右子树是满的,但是高度是左树的高度减一,剩下的节点递归去求。


public class NodeNumber {
	//求完全二叉树的结点数
	public static class Node{
		public int val;
		public Node left;
		public Node right;
		public Node(int x) {
			this.val = x;
		}
	}
	
	public static int nodenumber(Node root) {
		if(root == null)
			return 0;
		int h = 0;
		return nodenumber(root,h);
	}
	
	public static int nodenumber(Node root,int h) {
		if(root == null) {
			return 0;
		}
		Node tmp = root.left;
		int lh = 0;
		while(tmp != null) {
			tmp = tmp.left;
			lh++;
		}
		tmp = root.right;
		int rh = 0;
		while(tmp != null) {
			tmp = tmp.left;
			rh++;
		}
		if(lh > rh) {	
			h = (1 << rh) + nodenumber(root.left,h);//位运算的优先级低于加法的优先级!!要加上小括号
		}else {
			h = (1 << lh) + nodenumber(root.right,h);
		}
		return h;
	}
	
	public static void main(String[] args) {
		Node head = new Node(1);
		head.left = new Node(2);
		head.right = new Node(3);
		head.left.left = new Node(4);
		head.left.right = new Node(5);
		head.right.left = new Node(6);
		System.out.println(nodenumber(head));

	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值