引言
大家好,我是优快云的新手博主,今天给大家分享一篇关于树与二叉树的详细讲解。树是数据结构中非常重要的一部分,尤其在算法和数据处理中应用广泛。本文将从树的基本概念讲起,逐步深入到二叉树的实现,最后还会附上代码示例。希望能帮助到对树结构还不熟悉的小伙伴们!
1. 什么是树?
树(Tree)是n(n≥0)个节点的有限集合T,它满足以下两个条件:
-
有且仅有一个特定的称为**根(Root)**的节点。
-
其余的节点可以分为m(m≥0)个互不相交的有限集合T1、T2、...、Tm,其中每一个集合又是一棵树,并称为其根的子树(Subtree)。
树的特性:
-
层次关系,一对多。
-
每个节点最多有一个前驱,但可以有多个后继。
-
根节点无前驱,叶节点无后继。
2. 树的基本术语
-
度数:一个节点的子树的个数。
-
树度数:树中节点的最大度数。
-
叶节点:度数为零的节点。
-
分支节点:度数不为零的节点。
-
内部节点:除根节点以外的分支节点。
-
节点层次:根节点的层次为1,根节点子树的根为第2层,以此类推。
-
树的深度或高度:树中所有节点层次的最大值。
3. 二叉树
二叉树是每个节点最多只有两个子节点的树,分别称为左孩子和右孩子。
3.1 二叉树的定义
二叉树(Binary Tree)是n(n≥0)个节点的有限集合,它或者是空集(n=0),或者是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成。
3.2 二叉树的性质
-
二叉树第k(k≥1)层上的节点最多为2^(k-1)个。
-
深度为k(k≥1)的二叉树最多有2^k - 1个节点。
-
在任意一棵二叉树中,叶节点的数目比度数为2的节点的数目多一。
3.3 满二叉树和完全二叉树
-
满二叉树:深度为k(k≥1)时节点数为2^k - 1。
-
完全二叉树:只有最下面两层有度数小于2的节点,且最下面一层的叶节点集中在最左边的若干位置上。
4. 二叉树的存储结构
4.1 顺序存储结构
完全二叉树的节点编号方法是从上到下,从左到右,根节点为1号节点。设完全二叉树的节点数为n,某节点编号为i:
-
当i>1时,其父节点编号为i/2。
-
当2i <= n时,有左孩子,其编号为2i。
-
当2i+1 <= n时,有右孩子,其编号为2i+1。
4.2 链式存储结构
用链表实现,基于完全二叉树规律来构建树。每个节点包含数据域、左子节点指针和右子节点指针。
5. 二叉树的遍历
二叉树的遍历是树结构中的重点,常见的遍历方式有三种:
-
前序遍历:根 -> 左 -> 右
-
中序遍历:左 -> 根 -> 右
-
后序遍历:左 -> 右 -> 根
代码实现
以下是二叉树的创建和遍历的C语言实现:
#include <stdio.h>
#include <stdlib.h>
typedef struct tree_node {
int data;
struct tree_node *lchild;
struct tree_node *rchild;
} tree_node_t, *tree_node_p;
// 创建二叉树
tree_node_p CreateBitree(int n, int i) {
if (i > n) return NULL;
tree_node_p r = (tree_node_p)malloc(sizeof(tree_node_t));
if (NULL == r) {
perror("r malloc err");
return NULL;
}
r->data = i;
r->lchild = CreateBitree(n, 2 * i);
r->rchild = CreateBitree(n, 2 * i + 1);
return r;
}
// 前序遍历
void PreOrder(tree_node_p r) {
if (r == NULL) return;
printf("%d ", r->data);
PreOrder(r->lchild);
PreOrder(r->rchild);
}
// 中序遍历
void InOrder(tree_node_p r) {
if (r == NULL) return;
InOrder(r->lchild);
printf("%d ", r->data);
InOrder(r->rchild);
}
// 后序遍历
void PostOrder(tree_node_p r) {
if (r == NULL) return;
PostOrder(r->lchild);
PostOrder(r->rchild);
printf("%d ", r->data);
}
int main() {
tree_node_p root = CreateBitree(5, 1);
printf("前序遍历: ");
PreOrder(root);
printf("\n");
printf("中序遍历: ");
InOrder(root);
printf("\n");
printf("后序遍历: ");
PostOrder(root);
printf("\n");
return 0;
}
6. 哈夫曼树
哈夫曼树(Huffman Tree)是一种带权路径长度最短的二叉树,常用于数据压缩。它的构造规则如下:
-
将n个权值看作n棵树的森林。
-
选出两个根节点权值最小的树合并,作为一棵新树的左、右子树,且新树的根节点权值为其左、右子树根节点权值之和。
-
重复上述步骤,直到森林中只剩一棵树为止。