提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、概念及性质
1、概念
一棵二叉树是结点的一个有限集合,该集合:
1. 或者为空
2. 或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成
二叉树是一种非线性数据结构
结点的度:一个结点含有子树的个数称为该结点的度;
树的度:一棵树中,所有结点度的最大值称为树的度;
叶子结点或终端结点:度为0的结点称为叶结点;
双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父亲结点;
孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点;
根结点:一棵树中,没有双亲结点的结点;
结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推
树的高度或深度:树中结点的最大层次
两种特殊的二叉树
2、二叉树的性质
1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有 (i>0) 个结点
2、若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点数是2^(k-1) (k>=0)
3. 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
4、具有n个结点的完全二叉树的深度k为log2(1+n)上取整
5、对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的结点有:
若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
若2i+1<n,左孩子序号:2i+1,否则无左孩子
若2i+2<n,右孩子序号:2i+2,否则无右孩子
若总结点数为奇数:n1(度为1) = 0;
若总结点数为偶数:n1(度为1) = 1
二、叉树相关操作
1、定义一个节点
//定义一个节点
static class TreeNode{
public char val;
public TreeNode left; //左节点
public TreeNode right; //右节点
public TreeNode(char val) {
this.val = val;
}
}
2、二叉树的创建
public class Main {
* public static int i = 0;
* public static void main(String[] args) {
* Scanner in = new Scanner(System.in);
* // 注意 hasNext 和 hasNextLine 的区别
* while (in.hasNextLine()) { // 注意 while 处理多个 case
* String str = in.nextLine();
* TreeNode root = createNode(str);
* inOrder(root);
* }
* }
* // 构建一棵二叉树
* public static TreeNode createNode(String str) {
*
* //遍历字符串
* TreeNode root = null;
* if ((str.charAt(i)) != '#') { //代表为空
* //根据前序遍历遍历二叉树
* root = new TreeNode(str.charAt(i));
* i++;
* root.left = createNode(str);
* root.right = createNode(str);
* } else {
* i++;
* }
* //返回根节点
* return root;
3、前序遍历
NLR:前序遍历(Preorder Traversal 亦称先序遍历)——>访问根结点——>根的左子树——>根的右子树。
前序遍历的两种方式:递归非递归
/前序遍历
void preOrder(TreeNode root){
if (root == null){
return;
}
//递归思想
System.out.print(root.val+" "); //根
preOrder(root.left); //左
preOrder(root.right); //右
}
//非递归前序遍历
void preOrderNor(TreeNode root){
if (root == null){
return;
}
//定义栈
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()){
while(cur != null){
stack.push(cur);
System.out.print(cur.val+" ");
cur = cur.left;
}
TreeNode top = stack.pop();
cur = top.right;
}
}
4、中序遍历
中序遍历(Inorder Traversal)——根的左子树—>根节点—>根的右子树。
//中序遍历
void inOrder(TreeNode root){
if (root == null){
return;
}
inOrder(root.left);
System.out.print(root.val+" ");
inOrder(root.right);
}
//非递归中序遍历
void inOrderNor(TreeNode root){
if (root == null){
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur1 = root;
while (cur1 != null || !stack.isEmpty()){
while(cur1 != null){
stack.push(cur1);
cur1 = cur1.left;
}
TreeNode top = stack.pop();
System.out.print(top.val+" ");
cur1 = top.right;
}
}
4、后续遍历
后序遍历(Postorder Traversal)——根的左子树—>根的右子树—>根节点
//后序遍历
void postOrder(TreeNode root){
if (root == null){
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val+" ");
}
//非递归后续遍历
void postOrderNor(TreeNode root){
if (root == null){
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode prev = null;
while(cur != null || !stack.isEmpty()){
while (cur != null){
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.peek();
if (top.right == null ||top.right == prev){ //右边为空 或 右边已经打印完成
System.out.print(top.val+" ");
stack.pop();
prev = top; //记录下最新被打印的节点
}else {
cur = top.right;
}
}
}
5、计算树中的节点个数
```bash
public int nodeSize;
/**
* 计算树中的节点个数
* @param root
* @return
*/
//1、遍历思路
int size(TreeNode root){
if (root == null){
return 0;
}
nodeSize++;
size(root.left);
size(root.right);
return nodeSize;
}
//2、子问题思路
int size1(TreeNode root){
if (root == null){
return 0;
}
return size1(root.left)+size1(root.right)+1;
}
6、计算树中的叶子节点个数
```bash
// 获取叶子节点的个数
//1、遍历思路
int getLeafNodeCount1(TreeNode root){
int leafSize = 0;
if (root == null){
return 0;
}
if (root.left == null && root.right == null){
leafSize++;
}
getLeafNodeCount1(root.left);
getLeafNodeCount1(root.right);
return leafSize;
}
//2、子问题思路
int getLeafNodeCount(TreeNode root){
if (root == null){
return 0;
}
if (root.left == null && root.right == null){
return 1;
}
return getLeafNodeCount(root.left)+getLeafNodeCount(root.right);
}
``
提示:更多二叉树相关操作见码云:https://gitee.com/xu-ge-learning-code/javase/blob/6937b5c715586a482f364bf93f54ab73cd02d499/JAVASJ013/JAVASJ10/src/BinaryTree.java