简单地来说,满足以下两个条件的树就是二叉树:
- 本身是有序树;
- 树中包含的各个节点的度不能超过 2,即只能是 0、1 或者 2;
二叉树的性质
二叉树具有以下几个性质:
- 二叉树中,第 i 层最多有 2i-1 个结点。
- 如果二叉树的深度为 K,那么此二叉树最多有2K-1 个结点。
- 包含n个结点的二叉树的高度至少为(log2n)+1
二叉树还可以继续分类,衍生出满二叉树和完全二叉树。 满二叉树
满二叉树
如果二叉树中除了叶子结点,每个结点的度都为 2,则此二叉树称为满二叉树。
上图就是一个满二叉树。
满二叉树除了满足普通二叉树的性质,还具有以下性质:
满二叉树中不存在度为 1 的节点,每一个分支点中都两棵深度相同的子树,且叶子节点都在最底层。
完全二叉树
如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。
像左图就是一个完全二叉树,而右图没有按照从左到右的结构去分布,只能算是一个普通的二叉树。可以看看这篇的 树的结构特性
完全二叉树的特性:
- 如果一棵完全二叉树的下标为n,那么当n为奇数的时候,它的父节点的下标就为(n+1)*2-1,如果n为偶数的话,那么它的节点的下标就为(n+1)*2。
- 一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。
对于任意一个结点 i ,完全二叉树还有以下几个结论成立:
- 当 i>1 时,父亲结点为结点 [i/2] 。(i=1 时,表示的是根结点,无父亲结点)
- 如果 2i>n(总结点的个数,则结点 i 肯定没有左孩子(为叶子结点);否则其左孩子是结点 2i 。
- 如果 2i+1>n ,则结点 i 肯定没有右孩子;否则右孩子是结点 2i+1 。
来一个练习题
题目描述:输入一个二叉树,输出其镜像。
/*
* 题目描述:输入一个二叉树,输出其镜像。
*/
public class Solution {
Scanner scanner = new Scanner(System.in);
// 建立二叉树
public TreeNode createTree(TreeNode root) {
String val;
val = scanner.next(); // next方法每次取到一个间隔符前面的数据
if (val.equals("#")) {
return null;
}
root = new TreeNode(Integer.parseInt(val));
System.out.println("输入的数据为:" + val);
root.left = createTree(root.left);
root.right = createTree(root.right);
return root;
}
// 得到二叉树的镜像 —— 递归的方式
public void Mirror(TreeNode root) {
if (root == null) {
return;
}
if ((root.left == null) && (root.right == null)) {
return;
}
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
Mirror(root.left);
Mirror(root.right);
}
// 得到二叉树的镜像 —— 不使用递归
public void MirrorNotRecursive(TreeNode root) {
LinkedList stack = new LinkedList();
TreeNode temp = null;
if (root == null) {
return;
}
stack.add(root);
while (stack.size() != 0) {
TreeNode node = (TreeNode) stack.removeFirst();
temp = node.left;
node.left = node.right;
node.right = temp;
if (node.right != null) {
stack.add(node.right);
}
if (node.left != null) {
stack.add(node.left);
}
}
}
// 层次遍历二叉树
public void levelTraverse(TreeNode root) {
if (root == null) {
return;
}
LinkedList list = new LinkedList();
list.add(root);
while (list.size() != 0) {
TreeNode node = (TreeNode) list.removeFirst(); // list.removeFirst() 该方法LinkedList才有
System.out.print(node.val + " ");
if (node.left != null) {
list.add(node.left);
}
if (node.right != null) {
list.add(node.right);
}
}
}
public static void main(String[] args) {
Solution solution = new Solution();
TreeNode root = null;
root = solution.createTree(root);
System.out.println("原二叉树的层次遍历");
solution.levelTraverse(root);
solution.Mirror(root);
System.out.println("\n输出该二叉树的镜像");
solution.levelTraverse(root);
solution.MirrorNotRecursive(root);
System.out.println("\n输出该二叉树的镜像(非递归方式)");
solution.levelTraverse(root);
}
}
/*
*
* 测试数据:
*
* 1 2 3 # 4 # # 5 6 # # # 7 8 # # 9 10 # # 11 # # (说明:其中#说明左右子树为空)
*
* 用先序遍历来建立树后,层次遍历结果为: 1 2 7 3 5 8 9 4 6 10 11
*
* 反转二叉树之后:1 7 2 9 8 5 3 11 10 6 4
*
*/