1、基本术语
- 结点:树里面的元素。
- 父子关系:结点之间相连的边
- 子树:当结点大于1时,其余的结点分为的互不相交的集合称为子树
- 度:一个结点拥有的子树数量称为结点的度
- 叶子:度为0的结点
- 孩子:结点的子树的根称为孩子结点
- 双亲:和孩子结点对应
- 兄弟:同一个双亲结点
- 森林:由N个互不相交的树构成深林
- 结点的高度:结点到叶子结点的最长路径
- 结点的深度:根结点到该结点的边个数
- 结点的层数:结点的深度加1
- 树的高度:根结点的高度
2、图解
3、树的分类
定义:每个节点至多只有两颗子树
- 平衡二叉树(AVL树):是一种二叉排序树,是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
- 二叉查找树(二叉排序树):也叫二叉搜索树
定义:一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
- B树(B-Tree,B+Tree)
- 红黑树:是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但对之进行平衡的代价较低, 其平均统计性能要强于 AVL。
性质:红黑树是每个结点都带有颜色属性的二叉查找树,颜色或红色或黑色。 在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
- 结点是红色或黑色;
- 根结点是黑色;
- 所有叶子都是黑色;
- 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点);
- 从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。
4、二叉树简单实现
package algorithm.tree;
class MyTreeNode{
private char data;
private MyTreeNode left;
private MyTreeNode right;
public MyTreeNode(char data, MyTreeNode left, MyTreeNode right) {
super();
this.setData(data);
this.setLeft(left);
this.setRight(right);
}
public char getData() {
return data;
}
public void setData(char data) {
this.data = data;
}
public MyTreeNode getLeft() {
return left;
}
public void setLeft(MyTreeNode left) {
this.left = left;
}
public MyTreeNode getRight() {
return right;
}
public void setRight(MyTreeNode right) {
this.right = right;
}
}
public class BinaryTree {
public static void main(String[] args) {
MyTreeNode D = new MyTreeNode('D', null, null);
MyTreeNode H = new MyTreeNode('H', null, null);
MyTreeNode K = new MyTreeNode('K', null, null);
MyTreeNode C = new MyTreeNode('C', D, null);
MyTreeNode G = new MyTreeNode('G', H, K);
MyTreeNode B = new MyTreeNode('B', null, C);
MyTreeNode F = new MyTreeNode('F', G, null);
MyTreeNode E = new MyTreeNode('E', null, F);
MyTreeNode A = new MyTreeNode('A', B, E);
BinaryTree binaryTree = new BinaryTree();
System.out.println("前");
binaryTree.pre(A);
System.out.println();
System.out.println("中");
binaryTree.in(A);
System.out.println();
System.out.println("后");
binaryTree.post(A);
}
public void print(MyTreeNode node){
System.out.print(node.getData());
}
public void pre(MyTreeNode root){ //前序遍历 根(输出) 左 右 时间复杂度?O(n) N^2 O(2*n)=>O(n);
print(root);
if(root.getLeft() != null){
pre(root.getLeft()); //认为是子树,分解子问题;
}
if(root.getRight() != null){
pre(root.getRight());
}
}
public void in(MyTreeNode root){ //中序遍历 左 根(输出) 右
if(root.getLeft() != null){
in(root.getLeft()); //认为是子树,分解子问题;
}
print(root);
if(root.getRight() != null){
in(root.getRight());
}
}
public void post(MyTreeNode root){ //后序遍历 左 右 根(输出)
if(root.getLeft() != null){
post(root.getLeft()); //认为是子树,分解子问题;
}
if(root.getRight() != null){
post(root.getRight());
}
print(root);
}
}