二叉树介绍
二叉树是计算机科学中的一种基本数据结构,它是一种树形结构,其中每个节点最多有两个子节点,这两个子节点通常被称为左子节点和右子节点。二叉树的定义通常包括以下几个要点:
1. **节点定义**:每个节点包含三个部分:一个数据元素、一个指向左子节点的指针、一个指向右子节点的指针。
2. **根节点**:二叉树有一个特殊的节点,称为根节点,它没有父节点。
3. **子树**:每个节点的子树可以为空,也可以是一棵完整的二叉树。
4. **层级**:二叉树的层级从根节点开始,根节点位于第0层,其子节点位于第1层,依此类推。
5. **边**:节点之间的连接称为边。
6. **叶节点**:没有子节点的节点称为叶节点或终端节点。
7. **高度和深度**:二叉树的高度是从根节点到最远叶节点的最长路径上的边数。节点的深度是从根节点到该节点的路径上的边数。
8. **完全二叉树**:如果除了最后一层外,每一层都被完全填满,并且所有节点都尽可能地集中在左侧,则该二叉树是完全二叉树。
9. **满二叉树**:如果每一层都被完全填满,并且所有叶子节点都位于最底层,则该二叉树是满二叉树。
10. **平衡二叉树**:如果对于树中的每个节点,其两个子树的高度差不超过1,则该二叉树是平衡的。
二叉树在计算机科学中有着广泛的应用,包括但不限于搜索算法(如二叉搜索树)、排序算法(如归并排序)、表达式树的构建和解析等。
二叉树的三种遍历方式
二叉树的遍历是指按照某种规则访问树中的每个节点,确保每个节点被访问一次。二叉树的三种主要遍历方式是前序遍历、中序遍历和后序遍历。下面是每种遍历方式的详细说明:
- 前序遍历 (Pre-order Traversal):
-
- 访问顺序:根节点 -> 左子树 -> 右子树。
- 首先访问根节点,然后递归地进行前序遍历左子树,接着递归地进行前序遍历右子树。
- 这种遍历方式通常用于创建树的副本、打印树的结构等。
- 中序遍历 (In-order Traversal):
-
- 访问顺序:左子树 -> 根节点 -> 右子树。
- 首先递归地进行中序遍历左子树,然后访问根节点,最后递归地进行中序遍历右子树。
- 对于二叉搜索树,中序遍历可以得到节点值的有序序列。
- 后序遍历 (Post-order Traversal):
-
- 访问顺序:左子树 -> 右子树 -> 根节点。
- 首先递归地进行后序遍历左子树,然后递归地进行后序遍历右子树,最后访问根节点。
- 这种遍历方式通常用于删除树、计算树的深度等。
-
代码示例
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
List<Integer> listp= firstScan(p);
List<Integer> listq= firstScan(q);
if(listp.size() != listq.size()){
return Boolean.FALSE;
}
Boolean flag1 = Boolean.TRUE;
for(int index=0;index<listp.size() ;index++){
if(listp.get(index)!=listq.get(index)){
flag1 = Boolean.FALSE;
break;
}
}
listp= afterScan(p);
listq= afterScan(q);
if(listp.size() != listq.size()){
return Boolean.FALSE;
}
Boolean flag2 = Boolean.TRUE;
for(int index=0;index<listp.size() ;index++){
if(listp.get(index)!=listq.get(index)){
flag2 =Boolean.FALSE;
break;
}
}
listp= middleScan(p);
listq= middleScan(q);
if(listp.size() != listq.size()){
return Boolean.FALSE;
}
Boolean flag3 = Boolean.TRUE;
for(int index=0;index<listp.size() ;index++){
if(listp.get(index)!=listq.get(index)){
flag3 = Boolean.FALSE;
break;
}
}
return flag1 && flag2 && flag3;
}
/**
根据中序遍历结果构建数组
*/
public List<Integer> middleScan(TreeNode node){
List<Integer> list = new ArrayList<Integer>();
if(null == node){
return list;
}
if(node.left!=null){
list.addAll(middleScan(node.left));
}
list.add(node.val);
if(node.right!=null){
list.addAll(middleScan(node.right));
}
return list;
}
/**
根据前序遍历结果构建数组
*/
public List<Integer> firstScan(TreeNode node){
List<Integer> list = new ArrayList<Integer>();
if(null == node){
return list;
}
list.add(node.val);
if(node.left!=null){
list.addAll(firstScan(node.left));
}
if(node.right!=null){
list.addAll(firstScan(node.right));
}
return list;
}
/**
根据后续遍历结果构建数组
*/
public List<Integer> afterScan(TreeNode node){
List<Integer> list = new ArrayList<Integer>();
if(null == node){
return list;
}
if(node.left!=null){
list.addAll(afterScan(node.left));
}
if(node.right!=null){
list.addAll(afterScan(node.right));
}
list.add(node.val);
return list;
}
}