二叉树
# 树
一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它
叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 树是递归定义的,任何一颗树都是由根和子树构成的。
# 树的专有名词
根节点:没有父节点的节点
节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为3
叶节点或终端节点:度为0的节点称为叶节点; 如上图:I、G、K、L、M...等节点为叶节点
非终端节点或分支节点:度不为0的节点;
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的子节点
兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点
树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为3
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度:树中节点的最大层次; 如上图:树的高度为4
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
# 孩子兄弟表示法
左孩子右兄弟
# 二叉树
二叉树是n个结点的有限集合,该集合或者为空,或者是由一个根结点加上两棵分别称为左子树和右子树的二叉树组成。
二叉树的特点:
1. 每个结点最多有两个棵子树,即二叉树不存在度大于2的结点。
2. 二叉树的子树有左右之分,其子树的次序不能颠倒。
# 性质
- 性质一:若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2i-1个结点。
- 性质二:若规定根结点的层数为1,则深度为h的二叉树的最大结点数为2h-1个。
- 性质三:对任何一棵二叉树,如果度为0的叶结点个数为n0,度为2的分支结点个数为n2,则有n0 = n2+1。
- 性质四:若规定根结点的层数为1,则具有N个结点的满二叉树的深度h = log2(N+1)。
- 性质五:对于具有N个结点的完全二叉树,如果按照从上至下、从左至右的数组顺序对所有结点从0开始编号,则对于序号为i的结点:
- 若 i > 0,则该结点的父结点序号为:( i - 1) / 2;若 i = 0,则无父结点。
- 若2i + 1 < N,则该结点的左孩子序号为:2i + 1;若2i + 1 >= N,则无左孩子。
- 若2i + 2 < N,则该结点的右孩子序号为:2i + 2;若2i + 2 >= N,则无右孩子。
# 特殊的二叉树
- 满二叉树:一个二叉树,如果每一层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为k,且结点总数是2k-1,则它就是满二叉树。
- 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K,有N个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至N的结点一一对应时称之为完全二叉树。要注意的是满二叉树是一种特殊的完全二叉树。
# 二叉树的实现
// 二叉树的实现
class BinaryTreeNode {
public:
BinaryTreeNode *left;
BinaryTreeNode *right;
int data;
BinaryTreeNode(int val) : left(nullptr), right(nullptr), data(val) {}
};
class BinaryTree {
public:
BinaryTreeNode *root;
BinaryTree() : root(nullptr) {}
BinaryTree(BinaryTreeNode *newroot) : root(newroot) {}
// 插入
void insert_left(BinaryTreeNode *root, int value);
void insert_right(BinaryTreeNode *root, int value);
// 遍历:
// 前中后、层序遍历
// 前序:中左右
void preOrder(BinaryTreeNode *node) {
if (node == nullptr) {
return;
}
cout << node->data << "->";
preOrder(node->left);
preOrder(node->right);
}
// 中序:左中右
void inOrder(BinaryTreeNode *node) {
if (node == nullptr) {
return;
}
inOrder(node->left);
cout << node->data << "->";
inOrder(node->right);
}
// 后序:左右中
void postOrder(BinaryTreeNode *node) {
if (node == nullptr) {
return;
}
postOrder(node->left);
postOrder(node->right);
cout << node->data << "->";
}
// 获取树的节点数
int getNodeSize(BinaryTreeNode *node) {
if (node == nullptr) {
return 0;
}
return 1 + getNodeSize(node->left) + getNodeSize(node->right);
}
// 层序遍历
// 使用队列queue
void levelOrder(BinaryTreeNode *node) {
queue<BinaryTreeNode *> q;
// 1、根节点进队列
// 2、队列不为空,出队头节点,并且把左右节点入队
// 3、直到队列为空结束
if (node == nullptr)
return;
q.push(node);
while (!q.empty()) {
cout << q.front()->data << "->";
if (q.front()->left) q.push(q.front()->left);
if (q.front()->right) q.push(q.front()->right);
q.pop();
}
}
// 销毁二叉树
void destory(BinaryTreeNode *node) {
if (node == nullptr)
return;
destory(node->right);
destory(node->left);
delete node;
}
~BinaryTree() {
destory(root);
}
};
void BinaryTree::insert_left(BinaryTreeNode *root, int value) {
if (root == nullptr)
return;
BinaryTreeNode node(value);
root->left = &node;
}
void BinaryTree::insert_right(BinaryTreeNode *root, int value) {
if (root == nullptr)
return;
BinaryTreeNode node(value);
root->right = &node;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
上次更新: 2025/01/22, 20:13:47