树Tree
树是一种数据结构,它由n(n>0)个有限节点组成具有层次结构关系的集合,像一颗倒挂的树,根向上,叶子向下。
二叉树
二叉树是一同特殊的树,二叉树中每一个节点最多只有2个节点。
-
二叉树层次从2层开始,在第i层最多有2^(i-1)个节点 如第二层最多2个节点 第三层最多4个节点
-
高度为k的二叉树 一共最多有2^k-1个节点
-
完美二叉树:又称满二叉树 最后一层的叶子界面是满的,就是满二叉树,满二叉树节点总数为 2^k - 1 k为层数
-
完全二叉树:所有叶子节点都在最后一层或者倒数第二层,如果在最后一层要求节点在左边连续,如果在倒数第二层要求节点在右边连续.
-
完满二叉树: 除了叶子节点所有节点都有2个子节点
常用术语:
- 节点 树上一个存储数据的单元
- 根节点 最顶层的节点
- 父节点 节点上连接的上一层节点
- 子节点 节点向下连接的节点
- 叶子节点 最后一层的节点 即没有子节点的节点
- 节点权 节点值
- 路径 从根节点出发到节点所经过的路线
- 层 节点在从根节点开始往下数 在第几层
- 高度 整棵树一共有多少层
- 子树 一个节点即他的子节点组成一个子树
- 森林 多颗子树组成森林
遍历说明
主要看父节点在什么时候输出
- 前序遍历 先输出父节点 再输出左子树 再输出右子树 1 2 4 5 3 6 7
- 中序遍历 先输出左子树 再输入父节点 再输出 右子树 4 2 5 1 6 3 7
- 后续遍历 先输出左子树 再输出右子树 再输出父节点 4 5 2 6 7 3 1
代码示例
- 删除思路
- 判断根节点是不是为空,不为空根节点是不是目标节点
- 因为目前的tree是一个单向的所以需要找他的子节点
- 如果是左子节点为目标节点 this.left = null 右子节点为目标节点 this.right=null
- 如果当前节点的左子节点不是目标节点且左子节点不为空 递归删除
- 当前节点左字节递归完毕之后,开始同样的方法递归右子树
public class BinaryTreeDemo {
/**
* 节点示意图
* 1
* / \
* 2 3
* / \
* 5 4
* 前序 1 2 3 5 4
* 中序 2 1 5 3 4
* 后序 2 5 4 3 1
*/
public static void main(String[] args) {
Node node1 = new Node(1, "员工1");
Node node2 = new Node(2, "员工2");
Node node3 = new Node(3, "员工3");
Node node4 = new Node(4, "员工4");
Node node5 = new Node(5, "员工5");
Node node6 = new Node(5, "员工6");
BinaryTree tree = new BinaryTree(node1);
node1.left = node2;
node1.right = node3;
node3.left = node5;
node3.right = node4;
// node5.right = node6;
// tree.preOrderTraversal();//12354
// System.out.println();
// tree.inOrderTraversal();//21534
// System.out.println();
// tree.postOrderTraversal();//25431
// System.out.println();
// System.out.println(tree.preOrderFind(5)); // 1 2 3 5 一共4次查找
// System.out.println(tree.inOrderFind(5)); // 2 1 5 一共3次
// System.out.println(tree.postOrderFind(5)); // 2 5 一共2次
tree.del2(3);
tree.preOrderTraversal();
}
}
class BinaryTree {
Node root;
public BinaryTree(Node root) {
this.root = root;
}
//删除
public void del2(int id) {
if (root == null) {
System.out.println("tree is empty!");
} else {
if (root.id == id) {
root = null;
} else {
root.del2(id);
}
}
}
//删除
public void del(int id) {
if (root == null) {
System.out.println("tree is empty!");
} else {
if (root.id == id) {
root = null;
} else {
root.del(id);
}
}
}
// 前序遍历
public void preOrderTraversal() {
if (root == null) {
System.out.println("tree is empty!");
} else {
root.preOrderTraversal();
}
}
// 中序遍历
public void inOrderTraversal() {
if (root == null) {
System.out.println("tree is empty!");
} else {
root.inOrderTraversal();
}
}
// 后序遍历
public void postOrderTraversal() {
if (root == null) {
System.out.println("tree is empty!");
} else {
root.postOrderTraversal();
}
}
// 前序查找
public Node preOrderFind(int no) {
if (root == null) {
System.out.println("tree is empty!");
return null;
} else {
return root.preOrderFind(no);
}
}
public Node inOrderFind(int no) {
if (root == null) {
System.out.println("tree is empty!");
return null;
} else {
return root.inOrderFind(no);
}
}
public Node postOrderFind(int no) {
if (root == null) {
System.out.println("tree is empty!");
return null;
} else {
return root.postOrderFind(no);
}
}
}
class Node {
Node left;
Node right;
int id;
Object data;
public Node(int id, Object data) {
this.data = data;
this.id = id;
}
@Override
public String toString() {
return "Node{" +
"id=" + id +
", data=" + data +
'}';
}
/**
* 前序遍历 先输出中间节点 再输出左节点 再出输出又节点
*/
public void preOrderTraversal() {
System.out.print(this + "\t");
if (this.left != null) {
this.left.preOrderTraversal();
}
if (this.right != null) {
this.right.preOrderTraversal();
}
}
/**
* 中序遍历 先左 再中 后右
*/
public void inOrderTraversal() {
if (this.left != null) {
this.left.inOrderTraversal();
}
System.out.print(this + "\t");
if (this.right != null) {
this.right.inOrderTraversal();
}
}
/**
* 后续遍历 左 -> 右 -> 中
*/
public void postOrderTraversal() {
if (this.left != null) {
this.left.postOrderTraversal();
}
if (this.right != null) {
this.right.postOrderTraversal();
}
System.out.print(this + "\t");
}
/**
* 前序遍历查找
*
* @param id
*/
public Node preOrderFind(int id) {
if (this.id == id) {
return this;
}
Node temp = null;
if (this.left != null) {
temp = this.left.preOrderFind(id);
}
// 左递归没找到尝试右递归
if (temp == null) {
if (this.right != null) {
temp = this.right.preOrderFind(id);
}
}
return temp;
}
// 中序查找
public Node inOrderFind(int id) {
Node temp = null;
if (this.left != null) {
temp = this.left.inOrderFind(id);
}
if (temp == null) {
if (this.id == id) {
return this;
}
if (this.right != null) {
temp = this.right.inOrderFind(id);
}
}
return temp;
}
/**
* 后序遍历查找
*
* @param id
* @return
*/
public Node postOrderFind(int id) {
Node temp = null;
if (this.left != null) {
temp = this.left.postOrderFind(id);
}
if (temp == null) {
if (this.right != null) {
temp = this.right.postOrderFind(id);
}
}
if (temp == null) {
return this.id == id ? this : null;
}
return temp;
}
/**
* 如果是叶子节点直接删除 ,如果不是叶子直接 规定 如果有左子树 将左子树提上来 没有左子树提右子树
*
* @param id
*/
public void del2(int id) {
// 叶子节点直接删除
if (this.left != null && this.left.id == id && this.left.left == null && this.left.right == null) {
this.left = null;
return;
}
if (this.right != null && this.right.id == id && this.right.left == null && this.right.right == null) {
this.right = null;
return;
}
// 左边非叶子节点 左子树不为空
if (this.left != null && this.left.id == id && this.left.left != null) {
this.left = this.left.left;
return;
}
// 左边非叶子节点 左子树为空 右子树不为空
if (this.left != null && this.left.id == id && this.left.left == null && this.left.right != null) {
this.left = this.left.right;
return;
}
// 右边非叶子节点 左子树不为空
if (this.right != null && this.right.id == id && this.right.left != null) {
this.right = this.right.left;
return;
}
// 右边非叶子节点 左子树为空 右子树不为空
if (this.right != null && this.right.id == id && this.right.left == null && this.right.right != null) {
this.right = this.right.right;
return;
}
// 往左递归
if (this.left != null) {
this.left.del2(id);
}
// 往右边递归
if (this.right != null) {
this.right.del2(id);
}
}
/**
* 最简单的删除,不管是不是叶子节点直接删除 如果是叶子节点删除 如果是不是叶子节点直接删除子树
*
* @param id
*/
public void del(int id) {
if (this.left != null && this.left.id == id) {
this.left = null;
return;
}
if (this.right != null && this.right.id == id) {
this.right = null;
return;
}
// 左节点递归删除
if (this.left != null) {
this.left.del(id);
}
// 右节点递归删除
if (this.right != null) {
this.right.del(id);
}
}
}