数据结构-树
定义
树是由节点和边组成的一种非线性数据结构。树中的每个节点都可以有零个或多个子节点,并且一个节点只有一个父节点(除了根节点)
特性
树(Tree)作为一种非线性数据结构,具有以下一般特性:
- 树由节点(Node)和边(Edge)组成:每个节点表示一个实体,边表示节点之间的关系。
- 树有一个根节点(Root):根节点是树的顶部节点,是树中所有节点的起点。
- 节点之间存在父子关系:除了根节点外,每个节点都有一个父节点和零个或多个子节点。父节点是子节点的直接上级,而子节点是父节点的直接下级。
- 节点的度(Degree):节点的度表示节点拥有的子节点数量。
- 节点的层级(Level):根节点的层级为1,其子节点的层级为2,以此类推。
- 节点的深度(Depth):节点的深度表示从根节点到该节点的路径长度,根节点的深度为0。
- 节点的高度(Height):节点的高度表示从该节点到其最远叶子节点的路径长度,叶子节点的高度为0。
- 子树(Subtree):树中的任意节点和其所有子孙节点组成的子树。
- 叶子节点(Leaf Node):没有子节点的节点称为叶子节点,也称为终端节点。
- 祖先节点和后代节点:节点的祖先节点是其到根节点的路径上的所有节点,节点的后代节点是其子节点和子节点的子节点。
- 路径(Path):从一个节点到另一个节点经过的边的序列。
- 森林(Forest):由多个互不相交的树组成的集合。
树的分类
- 二叉树(Binary Tree):每个节点最多有两个子节点,分别称为左子节点和右子节点。
- 二叉搜索树(Binary Search Tree):左子节点的值小于等于父节点的值,右子节点的值大于等于父节点的值。
- 完全二叉树(Complete Binary Tree):除了最后一层,其他层的节点都是满的,且最后一层的节点依次从左到右排列。
- 满二叉树(Full Binary Tree):每个节点都有零个或两个子节点,且所有的叶子节点都在同一层上。
- 平衡二叉树(Balanced Binary Tree):左子树和右子树的高度差不超过1的二叉树,常见的平衡二叉树有AVL树和红黑树。
- B树(B-Tree):一种多路搜索树,用于大规模数据存储和快速访问,常用于数据库和文件系统。
- 二叉堆(Binary Heap):一种特殊的完全二叉树,满足堆的性质,常用于实现优先队列。
- 树堆(Treap):一种随机化平衡二叉搜索树,结合了二叉搜索树和堆的性质。
- 字典树(Trie):一种用于高效存储和搜索字符串的树形数据结构。
- 赫夫曼树(Huffman Tree):用于实现赫夫曼编码的特殊二叉树,常用于数据压缩。
代码实现
1 树的节点,TreeNode类表示树中的一个节点,它具有一个整(val)和一个子节点列表(children);每个TreeNode对象都可以有零个或多个子节点,通过列表(List)来存储子节点
public class TreeNode<T> {
/**
* 用来存储节点的数值或数据,它为树的节点提供了附加的信息,
* 帮助对树进行操作和处理
*/
public T val;
/**
* 个子节点列表(children)。
* 每个TreeNode对象都可以有零个或多个子节点,通过列表(List<TreeNode>)来存储子节点
*/
List<TreeNode<T>> children;
public TreeNode(T val) {
this.val = val;
this.children = new ArrayList<>();
}
}
2 Tree类表示整棵树,它具有一个根节点(root),通过TreeNode对象来表示树的结构
public class Tree<T> {
TreeNode<T> root;
public Tree(TreeNode<T> root) {
this.root = root;
}
/**
* 添加子节点
*/
public void addChild(TreeNode<T> parent, TreeNode<T> child) {
parent.children.add(child);
}
/**
* 删除子节点
*/
public void removeChild(TreeNode<T> parent, TreeNode<T> child) {
parent.children.remove(child);
}
/**
* 修改节点值
*/
public void updateValue(TreeNode<T> node, T newVal) {
node.val = newVal;
}
/**
* 深度优先搜索(DFS)
*/
public TreeNode dfs(T target) {
return dfsHelper(root, target);
}
/**
* dfs(T target) 方法接收一个目标值作为参数,
* 以深度优先搜索的方式在树中查找匹配的节点,并返回找到的节点。如
* 果未找到匹配的节点,则返回 null
*/
private TreeNode<T> dfsHelper(TreeNode<T> node, T target) {
if (node == null) {
return null;
}
if (node.val.equals(target)) {
return node;
}
for (TreeNode<T> child : node.children) {
TreeNode<T> result = dfsHelper(child, target);
if (result != null) {
return result;
}
}
return null;
}
/**
* 广度优先搜索(BFS)
*/
public TreeNode<T> bfs(T target) {
if (root == null) {
return null;
}
List<TreeNode<T>> queue = new ArrayList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode<T> node = queue.remove(0);
if (node.val.equals(target)) {
return node;
}
queue.addAll(node.children);
}
return null;
}
}
3 简单的测试用例
public void testTree() {
// 创建树节点
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(5);
// 构建树结构
Tree tree = new Tree(node1);
tree.addChild(node1, node2);
tree.addChild(node1, node3);
tree.addChild(node2, node4);
tree.addChild(node3, node5);
// 测试增删改查操作
System.out.println("深度优先搜索结果:" + tree.dfs(4).val); // 输出:4
System.out.println("广度优先搜索结果:" + tree.bfs(5).val); // 输出:5
tree.updateValue(node3, 6);
tree.removeChild(node3, node5);
}