概念(重要)
节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为6
树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6
叶子节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I…等节点为叶节点
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点
**根结点:**一棵树中,没有双亲结点的结点;如上图:A
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
**树的高度或深度:**树中节点的最大层次; 如上图:树的高度为4
树与非树(图)的差别
二叉树的遍历-前中后序
根据访问结点操作发生位置命名
1. NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
2. LNR:中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
3. LRN:后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根 的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。
// 前序遍历 void preOrderTraversal(Node root);
// 中序遍历 void inOrderTraversal(Node root);
// 后序遍历 void postOrderTraversal(Node root);
// 遍历思路-求结点个数 static int size = 0; void getSize1(Node root);
// 子问题思路-求结点个数 int getSize2(Node root);
// 遍历思路-求叶子结点个数
static int leafSize = 0; void getLeafSize1(Node root);
// 子问题思路-求叶子结点个数 int getLeafSize2(Node root);
// 子问题思路-求第 k 层结点个数 int getKLevelSize(Node root);
// 查找 val 所在结点,没有找到返回 null // 按照 根 -> 左子树 -> 右子树的顺序进行查找 // 一旦找到,立即返回,不需要继续在其他位置查找 Node find(Node root, int val);
写代码实现这个树的先序遍历
package java0418;
public class TestTree {
static class Node {
public char val; //数据域
public Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
public Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
public Node (char val) {
this.val = val;
}
}
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 preOrder(Node root) {
if (root == null) {
return;
}
System.out.println(root.val + " ");
preOrder(root.left);
preOrder(root.right);
}
public static void main(String[] args) {
Node root = build();
preOrder(root);
}
}
还有一个重要的小点,我竟然不知道,实在是太羞耻了。
我在创建节点的时候,写成了双引号,运行时出现了类型转换错误。
我才知道,双引号默认是String型。单引号默认为字符型。
这个错误太低级了。
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');
加入中序程序
//中序遍历
public static void inOrder(Node root){
if (root == null ) {
return;
}
inOrder(root.left);
System.out.println(root.val + " ");
inOrder(root.right);
}
加入后序程序
//后序遍历
public static void postOrder (Node root) {
if (root == null) {
return;
}
postOrder(root.left); //先访问左节点
postOrder(root.right); //再访问右节点
System.out.println(root.val + " "); //之后访问根节点
}
其实只要简单的想的话,不一步一步分析,对递归有逻辑清晰的了解。
所谓后序就是先访问左节点,再访问右节点,之后访问根节点。但是由于二叉树的层数不止一层,递归程序会一步步分析往下推进,推到最后一个没有下层节点的左节点,再去找跟它同层同枝丫的右节点,再找到他们两个的根节点,再依次往上推进。
这就是后序,程序非常简单。
//先序遍历
public static void preOrder(Node root) {
if (root == null) {
return;
}
System.out.println(root.val + " ");
preOrder(root.left);
preOrder(root.right);
}