1、二叉树和链表类似,主要通过结点的组合来表示二叉树,下面为它的表达形式:
class Node {
public char val;
public Node left;
public Node right;
public Node(char val) {
this.val = val;
}
}
2、 下面将构建一个固定结构的二叉树,并对它进行 :①先序遍历,②中序遍历,③后序遍历,④求结点个数(使用子问题和遍历两种方式解决),⑤求叶子结点个数(使用子问题和遍历两种方式解决),⑥求第K层节点个数,⑦层序遍历。
(1)先序遍历:由根节点开始访问,在递归遍历左子树,最后递归遍历右子树。
(2)中序遍历:先递归遍历左子树,再访问根节点,最后递归遍历右子树。
(3)后序遍历:先递归遍历左子树,再递归遍历右子树,最后访问根节点
(4)求结点个数:可拆分问题为 1 + 左子树的节点个数 + 右子树的节点个数
(5)求叶子结点个数:可拆分问题为左子树叶子结点个数 + 右子树叶子结点个数
(6)求第K层节点个数:左子树第K-1层节点的个数 + 右子树第K-1层节点的个数
(7)按层访问,从上至下,从左到右。
package BinaryTree;
class Node {
public char val;
public Node left;
public Node right;
public Node(char val) {
this.val = val;
}
}
public class BinaryTree {
// 创建根节点,root = null即为空树
private static Node root = null;
//构建一棵树,且为一颗固定结构的树
public static Node build() {
Node A = new Node('A');
Node B = new Node('B');
Node C = new Node('C');
Node D = new Node('D');
Node E = new Node('E');
Node F = new Node('F');
Node G = new Node('G');
A.left = B;
A.right = C;
B.left = D;
B.right = E;
E.left = G;
C.right = F;
return A;
}
// 先序遍历
public static void prevOrder(Node root) {
// 先访问根节点,再递归遍历左子树,最后递归遍历右子树
if (root == null) {
// 空树不需要遍历
return;
}
System.out.print(root.val);
prevOrder(root.left);
prevOrder(root.right);
}
//中序遍历
public static void inOrder(Node root) {
// 先递归遍历左子树,再访问根节点,最后递归遍历右子树
if (root == null) {
// 空树不需要遍历
return;
}
inOrder(root.left);
System.out.print(root.val);
inOrder(root.right);
}
//后序遍历
public static void postOrder(Node root) {
//先递归遍历左子树,再递归遍历右子树,最后访问根节点
if (root == null) {
// 空树不需要遍历
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val);
}
//求节点个数--子问题思路
public static int size(Node root) {
if (root == null) {
return 0;
}
// 节点个数可以分解为:
// 1 + 左子树的节点个数 + 右子树的节点个数
return 1 + size(root.left) + size(root.right);
}
//求节点个数--遍历思路
//public static int treeSize = 0;
//public static void size(Node root) {
// if (root == null) {
// return;
// }
// treeSize++;
// size(root.left);
// size(root.right);
//}
//求叶子结点个数--子问题思路
public static int getLeafSize(Node root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return 1;
}
// 叶子结点可以分解为:
//左子树叶子结点个数 + 右子树叶子结点个数
return getLeafSize(root.left) + getLeafSize(root.right);
}
//求叶子结点个数--遍历思路
// public static int leafSize = 0;
// public static void getLeafSize(Node root) {
// if (root == null) {
// return;
// }
// if (root.left == null && root.right == null) {
// leafSize++;
// }
// getLeafSize(root.left);
// getLeafSize(root.right);
// }
//求第K层节点个数
public static int getKLevelSize(Node root, int k) {
// 特殊情况
if (root == null || k < 1) {
return 0;
}
if (k == 1) {
// 只有根节点
return 1;
}
//第K层节点分解:
//左子树第K-1层节点的个数 + 右子树第K-1层节点的个数
return getKLevelSize(root.left, k - 1)
+ getKLevelSize(root.right, k - 1);
}
//层序遍历
public static void levelOrder(Node root) {
if(root == null){
return null;
}
Queue<Node> queue =new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
Node cur = queue.poll();
System.out.print(cur.val+" ");
if(cur.left != null){
queue.offer(root.left);
}
if(cur.right != null){
queue.offer(root.right);
}
}
}
public static void main(String[] args) {
root = build();
prevOrder(root);
inOrder(root);
postOrder(root);
System.out.println(size(root));
System.out.println(getLeafSize(root));
System.out.println(getKLevelSize(root, 3));
}
}
注:树的很多操作,都是与递归紧密相连的,大多都是用递归来实现树的遍历