一、树概述
树是一种特殊的数据结构,他可以用来描述有分支的结构是由一个或者一个以上的有限集合组成,具有两个属性:一是存在一个特殊的节点,成为树根;二是其余节点分为n>=0个互斥集合,T1,T2,T3,……,Tn,每个集合成为子树。常用属性如下:
1、根节点
根节点是一个没有双亲结点的结点,一棵树中最多有一个根节点。
2、结点的深度
是指从根节点到该节点的路径长度。
3、结点的高度
是指从该节点到最深节点的路径长度。
4、树的高度
是树中所有结点高度的最大值,树的深度是树中所有结点深度的最大值,对于同一棵树,其深度和高度是相同的,但是对于各个结点,其深度和高度不一定相同。
二、二叉树分类
1、二叉树
如果一棵树中的每个结点有0,1或者2个孩子结点,那么这棵树就称为二叉树;空树也是一颗有效的二叉树,一颗二叉树可以看做是由根节点和两棵不相交的子树(分别称为左子树和右子树)组成。
2、满二叉树
二叉树中的每个结点恰好有两个孩子结点且所有叶子结点都在同一层。
3、完全二叉树
完全二叉树从根结点到倒数第二层满足满二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。
4、平衡二叉树
它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
5、线索二叉树
通过考察各种二叉链表,不管儿叉树的形态如何,空链域的个数总是多过非空链域的个数。准确的说,n各结点的二叉链表共有2n个链域,非空链域为n-1个,但其中的空链域却有n+1个。所谓的线索二叉树就是把这些所谓的空链加以利用,再指向其他结点,这些连接成为线索,而这个树就成为线索二叉树。
6、红黑树
不仅是具有二叉搜索树的属性,还具有平衡树的属性,有序且子树差不超过1,颜色规则:根节点和特殊节点(即叶节点下面两个虚无的节点和未填写的节点)是黑的,红节点的左右子节点是黑的,最重要的是对于每个节点,从该节点到子孙叶节点的所有路径包含相同数目的黑节点。
三、二叉树代码实现
主要介绍而二叉树的插入、查找、遍历。二叉树的遍历分为如下两类:
(1)深度优先遍历:从根节点出发,沿着左子树方向进行纵向遍历,直到找到叶子节点为止。然后回溯到前一个节点,进行右子树节点的遍历,直到遍历完所有可达节点为止。可分为前序遍历,中序遍历,后序遍历。
(2)广度优先遍历:从根节点出发,在横向遍历二叉树层段节点的基础上纵向遍历二叉树的层次。一般借助与队列实现。
1、创建二叉树节点public class Node {
//数据
public int value;
//左子树
public Node leftNode;
//右子树
public Node rightNode;
public Node(int value) {
this.value = value;
leftNode = null;
rightNode = null;
}
}
2、二叉树构造方法public class Tree {
//根节点
private Node root;
//当前节点
private Node currrent;
public Tree(){
root = null;
currrent = null;
}
}
3、插入二叉树/**
* 插入
*/
public void insert(int value) {
Node node = new Node(value);
if (root == null) {
root = node;
currrent = node;
root.rightNode = null;
root.leftNode = null;
return;
}
//当前节点重新指向根节点
currrent = root;
//循环遍历二叉树
while (true) {
if (value < currrent.value) {
//左节点
if (currrent.leftNode == null) {
//左节点设置值
currrent.leftNode = node;
currrent = currrent.leftNode;
return;
} else {
//左节点下面还有节点则向下移动一个节点
currrent = currrent.leftNode;
}
} else {
//右节点
if (currrent.rightNode == null) {
//右节点设置值
currrent.rightNode = node;
currrent = currrent.rightNode;
return;
} else {
//右节点下面还有节点,则向下移动一个节点
currrent = currrent.rightNode;
}
}
}
}
4、查找二叉树/**
* 查找
*/
public int find(int value) {
if (root == null) {
return -1;
} else {
Node current = root;
while (current.value != value) {
if (current.value > value) {
current = current.leftNode;
} else {
current = current.rightNode;
}
if (current == null) {
return -1;
}
}
return current.value;
}
}
5、前序遍历/**
* 前序遍历
*/
public void displayPre(Node root) {
if (root != null) {
System.out.print(root.value + " ");
displayMiddle(root.leftNode);
displayMiddle(root.rightNode);
}
}
6、中序遍历/**
* 中序遍历
*/
public void displayMiddle(Node root) {
if (root != null) {
displayMiddle(root.leftNode);
System.out.print(root.value + " ");
displayMiddle(root.rightNode);
}
}
7、后序遍历/**
* 后序遍历
*/
public void displayLast(Node root) {
if (root != null) {
displayMiddle(root.leftNode);
displayMiddle(root.rightNode);
System.out.print(root.value + " ");
}
}
8、获取根节点/**
* 获取根节点
*/
public Node getRoot() {
return root;
}
9、二叉树是否为空/**
* 判单二叉树是否为空
*/
public boolean isEmpty() {
return root == null;
}