声明:此博客涵盖众多二叉树知识点,完全可供学校期末考试,oj题完全可供提升对二叉树的理解
备注:二叉树习题部分画图展示步骤过于繁琐,文章内只省略展示,如果看不懂,私信博主录视频讲解!
通过本文章可以掌握:
1、树型结构的概念
2. 二叉树
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
树型结构具有以下特点:
图解上述概念:
至于树的递归定义:在后面二叉树实现再细说
声明:这些名词较为重要一点,需牢记
树的以下概念只需了解,在看书时只要知道是什么意思即可:
图解上述名词:
声明:该内容了解即可
树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,实际中树有很多种表示方式,如:双亲表示法,
孩子表示法、孩子双亲表示法、孩子兄弟表示法等等
最常用的是:孩子双亲表示法,孩子兄弟表示法
声明:笔试、面试、考研二叉树被问到的概率非常大,务必重视
一棵二叉树是结点的一个有限集合,该集合:
二叉树的模式图:
1、二叉树中每个结点最多有两个孩子,可以是一个、两个或者没有孩子,孩子的数量一定不会大于 2,所以二叉树中一定不存在度 > 2 的结点
2、二叉树的子树有左右之分,左右次序不能颠倒,因此二叉树是有序树,这里的有序指的不是大小,而是顺序有序
3、如果是一颗二叉树,那么它的每颗子树也一定都是二叉树
以下几种情况都可以被称为二叉树:
1、 满二叉树: 一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。
2、满二叉树模式图:
我们可以发现当层数为K的二叉树结点个数满足:2 ^ K - 1 时此二叉树为满二叉树
1、完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从0至n-1的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树
上面的概念简化后就是从二叉树的根结点开始编号,如果编号一直是连续的,那么这颗二叉树就是一颗完全二叉树,反之就不是完全二叉树
声明:学校数据结构期末考试常见题型
二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有二叉和三叉表示方式
孩子表示法:
孩子双亲表示法(AVL树,红黑树,B-树常使用此方法存储):
声明:所有二叉树的相关题目,基本都是通过某种遍历方式来解决的
所谓遍历:是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题(比如:打印节点内容、节点内容加1)
二叉树的遍历分为四种:前序遍历,中序遍历,后序遍历,层次遍历。他们的区别就是根结点的打印顺序不同
前序遍历顺序:根结点—》左子树—》右子树
前序遍历过程:
public void preOrder(BTNode root) {
if (root == null) {
return;
}
System.out.print(root.val + " ");
preOrder(root.left);
preOrder(root.right);
}
中序遍历:左子树—》根结点—》右子树
中序遍历过程:先访问左子树再打印根结点最后访问右子树
public void inOrder(TreeNode root){
if(root == null){
return;
}
inOrder(root.left);
System.out.print(root.val+" ");
inOrder(root.right);
}
后序遍历:左子树—》右子树—》根结点
后序遍历过程:先访问左右子树最后打印根结点
public void postOrder(TreeNode root){
if(root == null){
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val+" ");
}
类似于完全二叉树给每个结点编号后,按照结点编号顺序打印结点即可
练习前中后序遍历:
习题一、给定完全二叉树的层次遍历,求其前序序列结果
解题过程:
习题二、给定先序遍历和中序遍历的结果,确定一棵二叉树
解题过程:
习题三、给定中序遍历和后序遍历,确定一棵二叉树
解题过程:
习题四、已知两个序列结果相同,确定一棵二叉树
解题过程:
声明:针对于二叉树的问题建议使用子问题的思路,子问题思路为面试常考思路
int count = 0;
public int size(TreeNode root) {
if (root == null) {
return 0;
}
count++;
size(root.left);
size(root.right);
return count;
}
代码解析:
②、子问题思路
public int size2(TreeNode root) {
if (root == null) {
return 0;
}
return size2(root.left) + size2(root.right) + 1;
}
int leftCount = 0;
public int getLeafNodeCount(TreeNode root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
leftCount++;
}
getLeafNodeCount(root.left);
getLeafNodeCount(root.right);
return leftCount;
}
public int getLeafNodeCount2(TreeNode root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return 1;
}
return getLeafNodeCount2(root.left) + getLeafNodeCount2(root.right);
}
public int getKLevelNodeCount(TreeNode root, int k) {
if (root == null || k <= 0) {
return 0;
}
if (k == 1) {
return 1;
}
return getKLevelNodeCount(root.left, k - 1) + getKLevelNodeCount(root.right, k - 1);
}
public int getHeight(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(getHeight(root.left), getHeight(root.right)) + 1;
}
public TreeNode find(TreeNode root, char val) {
if (root == null) {
return null;
}
if (root.val == val) {
return root;
}
TreeNode ret = find(root.left, val);
if (ret != null) {
return ret;
}
ret = find(root.right, val);
if (ret != null) {
return ret;
}
return null;
}
public boolean isCompleteTree(TreeNode root) {
if (root == null) return true;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode cur = queue.poll();
if (cur != null) {
queue.offer(cur.left);
queue.offer(cur.right);
}else{
break;
}
}
for (TreeNode t : queue) {
if (t != null) {
return false;
}
}
return true;
}
声明:以下12道题为面试常考题型,务必掌握
leetcode – 100、相同的树
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
//情况1当p和q为空的位置不一致的时候
if((p == null && q != null) || (p != null && q == null)){
return false;
}else if(p == null && q == null){
return true;
}else if(p.val != q.val){
return false;
}
return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
}
LeetCode - 572、另一颗树的子树
①、题目:
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
private boolean isSameTree(TreeNode p,TreeNode q){
if(p != null && q == null || p == null && q != null){
return false;
}
if(p == null && q == null){
return true;
}
if(p.val != q.val){
return false;
}
return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(root == null || subRoot == null){
return false;
}
if(isSameTree(root,subRoot)){
return true;
}
if(isSubtree(root.left,subRoot)){
return true;
}
if(isSubtree(root.right,subRoot)){
return true;
}
return false;
}
}
LeetCode–100、二叉树最大深度
此题就是求二叉树的深度,可以翻看上面的基本操作解析,这里不过多赘述
class Solution {
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
}
}
LeetCode–110、判断一颗二叉树是否是平衡二叉树
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
private int getHeight(TreeNode root){
if(root == null){
return 0;
}
return Math.max(getHeight(root.left),getHeight(root.right)) + 1;
}
public boolean isBalanced(TreeNode root) {
if(root == null){
return true;
}
int lh = getHeight(root.left);
int rh = getHeight(root.right);
if(Math.abs(lh - rh) <= 1 && isBalanced(root.left) && isBalanced(root.right)){
return true;
}
return false;
}
}
④、代码改进
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
private int getHeight(TreeNode root){
if(root == null){
return 0;
}
int lh = getHeight(root.left);
int rh = getHeight(root.right);
if(lh >= 0 && rh >= 0 && Math.abs(lh - rh) <= 1){
return Math.max(lh,rh) + 1;
}
return -1;
}
public boolean isBalanced(TreeNode root) {
if(root == null){
return true;
}
return getHeight(root) >= 0;
}
}
LeetCode–101、对称二叉树
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
private boolean isSame(TreeNode leftRoot,TreeNode rightRoot){
if(leftRoot == null && rightRoot == null){
return true;
}
if(leftRoot == null || rightRoot == null){
return false;
}
if(leftRoot.val == rightRoot.val){
return isSame(leftRoot.left,rightRoot.right) &&
isSame(leftRoot.right,rightRoot.left);
}
return false;
}
public boolean isSymmetric(TreeNode root) {
if(root == null){
return true;
}
return isSame(root.left,root.right);
}
}
牛客—KY11
①、题目:
import java.util.*;
class TreeNode{
public char val;
public TreeNode left;
public TreeNode right;
public TreeNode(char val){
this.val = val;
}
}
public class Main{
public static int i = 0;
private static TreeNode createTree(String str){
TreeNode root = null;
if(str.charAt(i) != '#'){
root = new TreeNode(str.charAt(i));
i++;
root.left = createTree(str);
root.right = createTree(str);
}else{
i++;
}
return root;
}
private static void inOrder(TreeNode root){
if(root == null){
return;
}
inOrder(root.left);
System.out.print(root.val + " ");
inOrder(root.right);
}
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
while(scanner.hasNextLine()){
String str = scanner.nextLine();
TreeNode root = createTree(str);
inOrder(root);
}
}
}
LeetCode—102、二叉树的分层遍历
①、题目:
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
import java.util.*;
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> leveLorder = new ArrayList<List<Integer>>();
if(root == null){
return leveLorder;
}
Queue<TreeNode> qu = new LinkedList<>();
qu.offer(root);
while(!qu.isEmpty()){
int size = qu.size();
List<Integer> ret = new ArrayList<>();
while(size != 0){
TreeNode cur = qu.poll();
ret.add((int) cur.val);
if(cur.left != null){
qu.offer(cur.left);
}
if(cur.right != null){
qu.offer(cur.right);
}
size--;
}
leveLorder.add(ret);
}
return leveLorder;
}
}
LeetCode—236、给定一个二叉树, 找到该树中两个指定节点的最近公共祖先
①、题目
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null){
return null;
}
if( p == root || q == root){
return root;
}
TreeNode leftNode = lowestCommonAncestor(root.left,p,q);
TreeNode rightNode = lowestCommonAncestor(root.right,p,q);
if (leftNode != null && rightNode != null){
return root;
}
if(leftNode != null){
return leftNode;
}
if(rightNode != null){
return rightNode;
}
return null;
}
}
LeetCode—36、二叉树搜索树转换成排序双向链表
①、题目
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val,Node _left,Node _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
Node prev = null;
private void inOrder(Node root){
if(root == null) return;
inOrder(root.left);
root.left = prev;
if (prev != null){
prev.right = root;
}
prev = root;
inOrder(root.right);
}
public Node treeToDoublyList(Node root) {
if(root == null){
return null;
}
inOrder(root);
Node head = root;
while(head.left != null){
head = head.left;
}
Node tail = root;
while(tail.right != null){
tail = tail.right;
}
tail.right = head;
head.left = tail;
return head;
}
}
LeetCode—105、根据一棵树的前序遍历与中序遍历构造二叉树
①、题目:
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
int preIndex = 0;
private TreeNode creatTreeBypAndi(int[] preorder, int[] inorder,int begin,int end){
if(begin > end){
return null;
}
TreeNode root = new TreeNode(preorder[preIndex]);
int index = find(inorder,begin,end,preorder[preIndex]);
if(index == -1){
return null;
}
preIndex++;
root.left = creatTreeBypAndi(preorder,inorder,begin,index - 1);
root.right = creatTreeBypAndi(preorder,inorder,index + 1,end);
return root;
}
private int find(int[] inorder,int begin,int end, int key){
for(int i = begin; i <= end; i++){
if(inorder[i] == key){
return i;
}
}
return -1;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || inorder == null){
return null;
}
return creatTreeBypAndi(preorder,inorder,0,inorder.length - 1);
}
}
LeetCode—106、根据一棵树的中序遍历与后序遍历构造二叉树
②、解题过程:
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
int postIndex = 0;
private TreeNode createTreeByIandP(int[] inorder, int[] postorder,int begin,int end){
if (begin > end){
return null;
}
TreeNode root = new TreeNode(postorder[postIndex]);
int index = find(inorder,begin,end,postorder[postIndex]);
if(index == -1){
return null;
}
postIndex--;
root.right = createTreeByIandP(inorder,postorder,index + 1,end);
root.left = createTreeByIandP(inorder,postorder,begin,index - 1);
return root;
}
private int find(int[] inorder,int begin,int end, int key){
for(int i = begin; i <= end; i++){
if(inorder[i] == key){
return i;
}
}
return -1;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
postIndex = inorder.length - 1;
if(inorder == null || postorder == null){
return null;
}
return createTreeByIandP(inorder,postorder,0,inorder.length - 1);
}
}
LeetCode—606、二叉树创建字符串
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
private void treeToString(StringBuffer sb,TreeNode root){
if(root == null) return;
sb.append(root.val);
if(root.left != null){
sb.append("(");
treeToString(sb,root.left);
sb.append(")");
}else{
if(root.right == null){
return;
}else{
sb.append("()");
}
}
if(root.right != null){
sb.append("(");
treeToString(sb,root.right);
sb.append(")");
}else{
return;
}
}
public String tree2str(TreeNode root) {
if(root == null){
return null;
}
StringBuffer sb = new StringBuffer();
treeToString(sb,root);
return sb.toString();
}
}
LeetCode—144、二叉树前序非递归遍历实现
①、题目
注意:我们之前写过二叉树前序遍历的递归实现 这里采用非递归去实现
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
import java.util.*;
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
TreeNode cur = root;
Stack<TreeNode> stack = new Stack<>();
while(cur != null || !stack.isEmpty()){
while(cur != null){
list.add(cur.val);
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.pop();
cur = top.right;
}
return list;
}
}
LeetCode–94、二叉树中序非递归遍历实现
public void inOrder1(TreeNode root){
TreeNode cur = root;
Stack<TreeNode> stack = new Stack<>();
while(cur != null || !stack.isEmpty()){
while(cur != null){
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.pop();
System.out.print(top.val+" ");
cur = top.right;
}
}
③、详细代码:
public void lastOrder1(TreeNode root){
TreeNode cur = root;
TreeNode prev = null;
Stack<TreeNode> stack = new Stack<>();
while(cur != null || !stack.isEmpty()){
while(cur != null){
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.peek();
if(top.right == null || prev == top.right){
stack.pop();
System.out.print(top.val+" ");
prev = top;
}else{
cur = top.right;
}
}
}
以上就是二叉树博客的全部内容,几乎覆盖了所有二叉树的知识点,希望对大家的学习有一定帮助,如果哪里有疑问,或者哪里有错误,随时连续博主,博主24h随时在线,博主定尽全力帮助解决!感谢大家的支持!