6.10 二叉树

满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。

完全二叉树:完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。

二叉搜索树:也叫作二叉排序树

前面介绍的树,都没有数值的,而二叉搜索树是有数值的了,二叉搜索树是一个有序树

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉排序数

二叉平衡树(AVL):它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

二叉树数据结构:

  public class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode() {}
      TreeNode(int val) { this.val = val; }
      TreeNode(int val, TreeNode left, TreeNode right) {
          this.val = val;
          this.left = left;
          this.right = right;
      }
}

二叉树的层序遍历

 利用广度优先遍历(BFS):需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,DFS而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。

记着判断根节点是不是null!!!

    public List<List<Integer>> levelOrder(TreeNode root) {
    	List<List<Integer>> res=new LinkedList<>();
    	Queue<TreeNode> queue=new LinkedList<>();
    	//入队列
    	queue.offer(root);
    	while(!queue.isEmpty()) {
    		//记录每层的节点
    		List<Integer> result=new LinkedList<>();
    		TreeNode node;
    		int size=queue.size();
    		//此时size是每层的节点个数
    		for(int i=0; i<size; i++) {
    			//出队列
    			node=queue.poll();
    			result.add(node.val);
    			if(node.left!=null) {
    				queue.offer(node.left);
    			}
    			if(node.right!=null) {
    				queue.offer(node.right);
    			}
    		}
    		res.add(result);
    	}
    	return res;
    }

二叉树的层序遍历2

 public List<List<Integer>> levelOrderBottom(TreeNode root) {
    	List<List<Integer>> res=new LinkedList<>();
    	Queue<TreeNode> queue=new LinkedList<>();
    	//入队列
    	if(root!=null) queue.offer(root);
    	else return res;
    	while(!queue.isEmpty()) {
    		//记录每层的节点
    		List<Integer> result=new LinkedList<>();
    		TreeNode node;
    		int size=queue.size();
    		//此时size是每层的节点个数
    		for(int i=0; i<size; i++) {
    			//出队列
    			node=queue.poll();
    			result.add(node.val);
    			if(node.left!=null) {
    				queue.offer(node.left);
    			}
    			if(node.right!=null) {
    				queue.offer(node.right);
    			}
    		}
    		res.add(result);
    	}
    	List<List<Integer>> ans=new LinkedList<>();
    	for(int i=res.size()-1; i>=0; i--) {
    		ans.add(res.get(i));
    	}
    	return ans;
    }

 二叉树的右视图

      public List<Integer> rightSideView(TreeNode root) {
    	List<Integer> res=new LinkedList<>();
    	Queue<TreeNode> queue=new LinkedList<>();
    	//入队列
    	if(root!=null) queue.offer(root);
    	else return res;
    	while(!queue.isEmpty()) {
    		//记录每层的节点
    		TreeNode node;
    		int size=queue.size();
    		//此时size是每层的节点个数
    		for(int i=0; i<size; i++) {
    			//出队列
    			node=queue.poll();
    			if(i==size-1)res.add(node.val);
    			if(node.left!=null) queue.offer(node.left);
    			if(node.right!=null) queue.offer(node.right);
    		}
    	}
    	return res;
    }

还能用层序遍历解决一下问题:

  • 637.二叉树的层平均值
  • 429.N叉树的层序遍历
  • 515.在每个树行中找最大值
  • 116.填充每个节点的下一个右侧节点指针
  • 117.填充每个节点的下一个右侧节点指针II
  • 104.二叉树的最大深度
  • 111.二叉树的最小深度

二叉树的最大深度

DFS和BFS都可以做

DFS代码:

int res=0;
      public int maxDepth(TreeNode root) {
    	  if(root==null)return 0;
    	  dfs(root, res);
    	  return res;
      }
      public void dfs(TreeNode root, int deep) {
		if(root==null) {
			res=Math.max(deep, res);
            return;
		}
		dfs(root.left, deep+1);
		dfs(root.right, deep+1);
	}

翻转二叉树

这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!

      public TreeNode invertTree(TreeNode root) {
    	  if(root==null)return null;
    	  dfs(root);
    	  return root;
      }
      public void dfs(TreeNode root) {
		if(root==null)return;
		TreeNode tmpNode=new TreeNode();
		tmpNode=root.left;
		left=root.right;
		right=tmpNode;
		dfs(root.left);
		dfs(root.right);
	}

对称二叉树

思路:第一种思路:是先将本来的树根节点存起来,然后翻转得到另一个新树,再同时对两棵遍历去比较结点的值是否相等,但是要遍历两次树,复杂度很高。

直接一次遍历就可以:可以以根节点为中心,相等于比较左子树、右子树的外侧是否相等,左子树、右子树的内测是否相等。

确定终止条件有一些复杂:自己想的时候总是会漏掉部分终止条件,但是递归这种东西终止条件一定要写对,否则不能AC。

要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚!否则后面比较数值的时候就会操作空指针了。

节点为空的情况有:(注意我们比较的其实不是左孩子和右孩子,所以如下我称之为左节点右节点

  • 左节点为空,右节点不为空,不对称,return false
  • 左不为空,右为空,不对称 return false
  • 左右都为空,对称,返回true

此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:

  • 左右都不为空,比较节点数值,不相同就return false
public boolean isSymmetric(TreeNode root) {
    	  if(root==null)return true;
    	  return dfs(root.left, root.right);   	   
      }
      
      public boolean dfs(TreeNode left, TreeNode right) {
		if(left==null && right==null)return true;
		else if(left==null && right!=null)return false;
		else if(left!=null && right==null)return false;
		else if(left.val!=right.val)return false;
		else {
            //比较内侧
			boolean a=dfs(left.left, right.right);
            //比较外侧
			boolean b=dfs(left.right, right.left);
			return a && b;
		}
	}

完全二叉树的节点个数

      public int countNodes(TreeNode root) {
    	  if(root==null) {
    		  return 0;
    	  }
    	  else {
    		  //这个+1是这道题的精髓,拿到此根结点就+1,再分别加上左、右节点的节点数
			return countNodes(root.left)+countNodes(root.right)+1;
		}
      }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值