1. 什么是二叉树
二叉树是树的一种,二叉树每个节点最多有两个子节点,即结点的度最大为 2。
结点的度:结点拥有的子节点个数。
树的深度:根节点到底层节点的层数。
二叉树的一些性质:
- 二叉树第 i 层上的结点数目最多为 2 ^ ( i - 1 ) ( i ≥ 1 )
- 深度为 h 的二叉树至多有 2 ^ h - 1 个结点 ( h ≥ 1 )
- 包含 n 个结点的二叉树的高度至少为 log 2 ( n + 1 )
- 在任意一棵二叉树中,若终端结点的个数为 n0,度为 2 的结点数为 n2,则 n0 = n2 + 1
二叉树的结构举例:
/**
*@ClassName: BinTree
*@Description: 二叉树类
*
*/
public class BinTree {
/**
*@ClassName: Node
*@Description: 内部类,表示二叉树的每一个节点
*
*/
private class Node {
// 每个节点的数据
private Object data;
// 左子树指针
private Node left;
// 右子树指针
private Node right;
}
}
// 二叉树的根节点
private Node rootNode;
}
2. 特殊的二叉树
斜树: 所有节点只有左子树或右子树
满二叉树: 所有的分支节点都具有左右节点
完全二叉树: 设二叉树深度为 h,除第 h 层外,其它各层 (1~h - 1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边。
二叉查找树: 当前根节点的左边全部比根节点小,当前根节点的右边全部比根节点大。
3. 二叉树的遍历
二叉树有三种遍历方式:先序遍历、中序遍历、后序遍历。
- 先序遍历:先访问根节点,然后访问左节点,最后访问右节点 ( 根 -> 左 -> 右 )。
- 中序遍历:先访问左节点,然后访问根节点,最后访问右节点 ( 左 -> 根 -> 右 )。
- 后序遍历:先访问左节点,然后访问右节点,最后访问根节点 ( 左 -> 右 -> 根 )。
举例:
先序遍历:1 2 4 8 9 5 10 3 6 7
中序遍历:8 4 9 2 10 5 1 6 3 7
后序遍历:8 9 4 10 5 2 6 7 3 1
使用案例:
package work.java.xzk10301002.bintree;
/**
*@ClassName: BinTree
*@Description: 二叉树类
*
*/
public class BinTree {
/**
*@ClassName: Node
*@Description: 内部类,表示二叉树的每一个节点
*
*/
private class Node {
// 每个节点的数据
private Object data;
// 左子树指针
private Node left;
// 右子树指针
private Node right;
public Node(Object data) {
this.data = data;
}
}
// 二叉树的根节点
private Node rootNode;
public Node getRootNode() {
return rootNode;
}
public BinTree() {
}
/**
* @Description //TODO 根据数组的数据创建一个二叉树
* @Param [dataArray] 数组
* @return void
**/
public void creatTreeByArray(Object[] dataArray) {
int end = dataArray.length - 1;
// 获得根节点并储存
this.rootNode = getNode(dataArray, 0, end);
}
/**
* @Description //TODO 使用递归的方法创建二叉树
* @Param [dataArray, start, end] dataArray为节点数据数组,start为数组第一个元素的索引,end为数组最后一个元素的索引
* @return work.java.xzk10301002.bintree.BinTree.Node 返回二叉树的根节点
**/
public Node getNode(Object[] dataArray, int start, int end) {
Node rootNode;
// 数组还有数据则二分
if (start <= end) {
// 获取数组中间值的索引
int middle = (start + end + 1) / 2;
// 以数组中间的数据为根节点创建节点
rootNode = new Node(dataArray[middle]);
// 使用递归创建当前根节点的左子树
rootNode.left = getNode(dataArray, start, middle - 1);
// 使用递归创建当前根节点的右子树
rootNode.right = getNode(dataArray, middle + 1, end);
} else {
// 二分后不存在数据了表示已经到了叶子节点的,叶子节点都指向null
rootNode = null;
}
// 递归出口,返回当前根节点
return rootNode;
}
/**
* @Description //TODO 使用递归的方式先序遍历二叉树
* @Param [rootNode] 二叉树的根节点
* @return void
**/
public void preorderTraversal(Node rootNode) {
// 递归出口,不存在该节点则返回上一层
if (rootNode == null) {
return;
}
// 先打印根节点信息
System.out.print(rootNode.data);
System.out.print(" ");
// 打印左子树
preorderTraversal(rootNode.left);
// 打印右子树
preorderTraversal(rootNode.right);
}
/**
* @Description //TODO 使用递归的方式中序遍历二叉树
* @Param [rootNode] 叉树的根节点
* @return void
**/
public void inorderTraversal(Node rootNode) {
if (rootNode == null) {
return;
}
inorderTraversal(rootNode.left);
System.out.print(rootNode.data);
System.out.print(" ");
inorderTraversal(rootNode.right);
}
/**
* @Description //TODO 使用递归的方式后序遍历二叉树
* @Param [rootNode] 叉树的根节点
* @return void
**/
public void postorderTraversal(Node rootNode) {
if (rootNode == null) {
return;
}
postorderTraversal(rootNode.left);
postorderTraversal(rootNode.right);
System.out.print(rootNode.data);
System.out.print(" ");
}
}
package work.java.xzk10301002.bintree;
/**
*@ClassName: BinTreeTest
*@Description: 二叉树遍历演示的启动类
*
*/
public class BinTreeTest {
public static void main(String[] args) {
Object[] dataArray = {1, 2, 3, 4, 5, 6, 7, 8, 9};
BinTree tree = new BinTree();
tree.creatTreeByArray(dataArray);
System.out.print("先序遍历二叉树:");
tree.preorderTraversal(tree.getRootNode());
System.out.println();
System.out.print("中序遍历二叉树:");
tree.inorderTraversal(tree.getRootNode());
System.out.println();
System.out.print("后序遍历二叉树:");
tree.postorderTraversal(tree.getRootNode());
}
}
运行结果: