一、定义
- 结点分类:树的结点包含一个数据元素和若干指向其子树的分支
- 度:结点拥有的子树数称为结点的度,度为0的结点称为叶子节点,树的结点时各结点度的最大值。
- 树的层数(深度):从根开始定义,根为第一层,树种的结点的最大层次称为树的深度或者高度。
二、树的存储结构
- 双亲表示法:在每个结点中,附设一个指示器指示双亲在数组中的位置
- 孩子表示法:在每个结点中,附设一个指示器指示孩子数和若干指示器指向孩子结点所在的位置
- 孩子兄弟表示法:data-firstchild-rightchild
三、二叉树的定义
- 满二叉树:在一棵二叉树中,所有分支结点都存在左子树和右子树,并且所有的叶子节点都在同一层上。
- 完全二叉树:完全二叉树是由满二叉树而引出来的,若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树),第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
四、二叉树的性质:
- 在二叉树的第I层上至少有2^i-1个结点
- 深度为K的二叉树至多有2^k-1个结点
- 对任意二叉树T,如果其叶子节点数为n0,度为2的结点数为n2,则n0=n2+1。
- 具有N个结点的完全二叉树的深度为|log2N|(|x|表示不大于x的最大整数)+1。
- 如果对一颗有N个结点的完全二叉数的结点按层数编号,对任意结点I有:
- 如果I等于1,则结点无双亲,如果I大于1,则双亲为|I/2|
- 如果2*I>N,则结点I无左孩子,否则其左孩子是结点2I.
- 如果2*I+1>N,则结点I无右孩子,否则其右孩子是结点2I+1.
五、二叉树的遍历
二叉树的四种遍历方式
前序遍历
中序遍历
后序遍历
层次遍历
遍历之前先创建一个二叉树
首先声明结点类
public class TreeNode {
public int data;
public TreeNode leftChild;
public TreeNode rightChild;
public TreeNode(int data){
this.data = data;
}
}
然后创建一颗二叉树
/**
* 构建二叉树
* @param list 输入序列
* @return
*/
public static TreeNode createBinaryTree(LinkedList<Integer> list){
TreeNode node = null;
if(list == null || list.isEmpty()){
return null;
}
Integer data = list.removeFirst();
if(data!=null){
node = new TreeNode(data);
node.leftChild = createBinaryTree(list);
node.rightChild = createBinaryTree(list);
}
return node;
}
前序遍历
实现代码:
/**
* 二叉树前序遍历 根-> 左-> 右
* @param node 二叉树节点
*/
public static void preOrderTraveral(TreeNode node){
if(node == null){
return;
}
System.out.print(node.data+" ");//根节点
preOrderTraveral(node.leftChild);//左子树
preOrderTraveral(node.rightChild);//右子树
}
中序遍历
代码实现:
/**
* 二叉树中序遍历 左-> 根-> 右
* @param node 二叉树节点
*/
public static void inOrderTraveral(TreeNode node){
if(node == null){
return;
}
inOrderTraveral(node.leftChild);
System.out.print(node.data+" ");
inOrderTraveral(node.rightChild);
}
后序遍历
代码实现:
/**
* 二叉树后序遍历 左-> 右-> 根
* @param node 二叉树节点
*/
public static void postOrderTraveral(TreeNode node){
if(node == null){
return;
}
postOrderTraveral(node.leftChild);
postOrderTraveral(node.rightChild);
System.out.print(node.data+" ");
}
层序遍历
代码实现:
public static void levelOrder(TreeNode root){
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
root = queue.pop();
System.out.print(root.data+" ");
if(root.leftChild!=null) queue.add(root.leftChild);
if(root.rightChild!=null) queue.add(root.rightChild);
}
}
非递归前序遍历
- 首先申请一个新的栈,记为stack;
- 声明一个结点treeNode,让其指向node结点;
- 如果treeNode的不为空,将treeNode的值打印,并将treeNode入栈,然后让treeNode指向treeNode的左结点,
- 重复步骤3,直到treenode为空;
- 然后出栈,让treeNode指向treeNode的右孩子
- 重复步骤3,直到stack为空.
代码实现:
public static void preOrderTraveralWithStack(TreeNode node){
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode treeNode = node;
while(treeNode!=null || !stack.isEmpty()){
//迭代访问节点的左孩子,并入栈
while(treeNode != null){
System.out.print(treeNode.data+" ");
stack.push(treeNode);
treeNode = treeNode.leftChild;
}
//如果节点没有左孩子,则弹出栈顶节点,访问节点右孩子
if(!stack.isEmpty()){
treeNode = stack.pop();
treeNode = treeNode.rightChild;
}
}
}