Skip to content

Commit 7432797

Browse files
committed
update images
1 parent dca4988 commit 7432797

File tree

1 file changed

+108
-20
lines changed

1 file changed

+108
-20
lines changed

content/09-datastruct-algorithm/05-tree.md

Lines changed: 108 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,15 @@ tags: ["数据结构", "算法", "树"]
125125
- 判断i是否有右孩子: 2i + 1 <= n
126126
- 判断i是否是叶子/分支节点: i > n / 2
127127

128-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/tree-array.jpg)
128+
![](https://s2.loli.net/2025/09/28/OUeyS9H7o1wLAXC.png)
129129

130130

131131
### 链式存储
132132

133133
- 可以简单找到p节点的左右节孩子,但只能通过从根开始遍历找到p的父节点
134134
- 可以多定义一个父节点指针来方便查找父节点
135135

136-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/tree-list.jpg)
136+
![](https://s2.loli.net/2025/09/28/X1gVH8myQBNcetL.png)
137137

138138

139139
## 二叉树遍历
@@ -145,16 +145,16 @@ tags: ["数据结构", "算法", "树"]
145145

146146
### 前序遍历
147147

148-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/tree-pre-order.jpg)
148+
![](https://s2.loli.net/2025/09/28/fn51EOekLZW4tDx.png)
149149

150150

151151
### 中序遍历
152152

153-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/tree-in-order.jpg)
153+
![](https://s2.loli.net/2025/09/28/O6Q4gidBP7tlaDH.png)
154154

155155
### 后序遍历
156156

157-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/tree-post-order.jpg)
157+
![](https://s2.loli.net/2025/09/28/8gms6ONM1WXGFrc.png)
158158

159159
### 层序遍历
160160

@@ -163,7 +163,7 @@ tags: ["数据结构", "算法", "树"]
163163
- 若队列非空,则队头节点处队,访问该节点,并将左右孩子插入队尾
164164
- 重复第三步,直到队列为空
165165

166-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/tree-level-order.jpg)
166+
![](https://s2.loli.net/2025/09/28/IOb1ulScfxPGrWJ.png)
167167

168168

169169
## 构造二叉树
@@ -189,22 +189,91 @@ tags: ["数据结构", "算法", "树"]
189189

190190
非递归
191191

192-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/bst-search.jpg)
192+
```c++
193+
// 在二叉排序树中查找值为key的结点
194+
BSTNode *BST_Search(BSTree T, int key) {
195+
// 若树空或等于根结点值,则结束循环
196+
while (T != NULL && key != T->key) {
197+
// 小于,则在左子树上查找
198+
if (key < T->key) T = T->lchild;
199+
// 大于,则在右子树上查找
200+
else T = T->rchild;
201+
}
202+
return T;
203+
}
204+
```
205+
206+
193207
194208
递归方式
195209
196-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/bst-search-track.jpg)
210+
```c++
211+
// 在二叉排序树中查找值为key的结点(递归实现)
212+
BSTNode *BSTSearch(BSTree T, int key) {
213+
if (T == NULL)
214+
// 查找失败
215+
return NULL;
216+
if (key == T->key)
217+
// 查找成功
218+
return T;
219+
else if (key < T->key)
220+
// 在左子树中找
221+
return BSTSearch(T->lchild, key);
222+
else
223+
// 在右子树中找
224+
return BSTSearch(T->rchild, key);
225+
}
226+
```
227+
228+
197229

198230
### 插入
199231

200232
- 二叉树为空,直接插入节点
201233
- 若关键字k小于根节点,插入左子树,否则插入右子树
202234

203-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/bst-insert.jpg)
235+
```c++
236+
// 在二叉排序树插入关键字为k的新结点(递归实现)
237+
int BST_Insert(BSTree &T, int k) {
238+
// 原树为空,新插入的结点为根结点
239+
if (T == NULL) {
240+
T = (BSTree)malloc(sizeof(BSTNode));
241+
T->key = k;
242+
T->lchild = T->rchild = NULL;
243+
// 返回1,插入成功
244+
return 1;
245+
}
246+
// 树中存在相同关键字的结点,插入失败
247+
else if (k == T->key)
248+
return 0;
249+
// 插入到T的左子树
250+
else if (k < T->key)
251+
return BST_Insert(T->lchild, k);
252+
// 插入到T的右子树
253+
else
254+
return BST_Insert(T->rchild, k);
255+
}
256+
```
257+
258+
204259
205260
### 构造
206261
207-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/bst-create.jpg)
262+
```c++
263+
// 按照 str[] 中的关键字序列建立二叉排序树
264+
void Creat_BST(BSTree &T, int str[], int n) {
265+
// 初始时T为空树
266+
T = NULL;
267+
int i = 0;
268+
// 依次将每个关键字插入到二叉排序树中
269+
while (i < n) {
270+
BST_Insert(T, str[i]);
271+
i++;
272+
}
273+
}
274+
```
275+
276+
208277

209278
### 删除
210279

@@ -254,7 +323,7 @@ LL平衡旋转
254323
- 将A节点向右下旋转称为B的右子树的根节点
255324
- B的原右子树则作为A节点的左子树
256325

257-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/avl-ll.jpg)
326+
![](https://s2.loli.net/2025/09/28/HzRmucb6hTVilxQ.png)
258327

259328
RR平衡旋转
260329

@@ -263,23 +332,23 @@ RR平衡旋转
263332
- 将A节点向左下旋转称为B的左子树的根节点
264333
- B的原左子树作为A节点的右子树
265334

266-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/avl-rr.jpg)
335+
![](https://s2.loli.net/2025/09/28/6PlLmFAX4kWHZTi.png)
267336

268337
LR平衡旋转
269338

270339
- 由于在A的左孩子的右子树插入了新节点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先左旋转后右旋转
271340
- 将A节点的左孩子的右子树的根节C点向左上旋转提升至节B节点的位置
272341
- 再把该C节点向右上旋转提升到A节点的位置
273342

274-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/avl-lr.jpg)
343+
![](https://s2.loli.net/2025/09/28/xUcgfSCA721ph8R.png)
275344

276345
RL平衡旋转
277346

278347
- 由于在A的右孩子(R)的左子树(L)上插入新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先右旋转后左旋转
279348
- 将A结点的右孩子B的左子树的根结点C向右上旋转提升到B结点的位置
280349
- 然后再把该C结点向左上旋转提升到A结点的位置
281350

282-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/avl-rl.jpg)
351+
![](https://s2.loli.net/2025/09/28/mH8CG2aw6WtPpFD.png)
283352

284353

285354
## 哈夫曼树
@@ -288,7 +357,7 @@ RL平衡旋转
288357

289358
- 在含有n个带权叶节点的二叉树中,其中带权路径长度(WPL)最小的二叉树称为哈夫曼树,也称最优二叉树
290359

291-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/hafman-tree.jpg)
360+
![](https://s2.loli.net/2025/09/28/M8OcCDtS1u3zsnW.png)
292361

293362
### 构造
294363

@@ -305,7 +374,7 @@ RL平衡旋转
305374
- 哈夫曼树中不存在度为1的节点
306375
- 哈夫曼树并不惟一,但WPL必然相同并最优
307376

308-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/hafman-create.jpg)
377+
![](https://s2.loli.net/2025/09/28/2rDpTL1sJlkj3R7.png)
309378

310379

311380
### 哈夫曼编码
@@ -325,11 +394,11 @@ RL平衡旋转
325394

326395
实际上就是树的双亲表示法,里面的值就是自己对应的根节点下标
327396

328-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/find-union-create.jpg)
397+
![](https://s2.loli.net/2025/09/28/6zwFP9fmEIdlt2y.png)
329398

330399
### 并、查
331400

332-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/find-union.jpg)
401+
![](https://s2.loli.net/2025/09/28/u9mRcO4TWMiQGIa.png)
333402

334403
### 并的优化
335404

@@ -338,15 +407,34 @@ RL平衡旋转
338407
- union操作让小树合并到大树
339408
- 查的最坏时间复杂度变为O($\log_2n$)
340409

341-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/union-best.jpg)
410+
![](https://s2.loli.net/2025/09/28/WpxoidVKEG8SfUl.png)
342411

343412

344413
### 压缩路径
345414

346415
- 核心思想就是让树越来越矮
347416
- Find操作先找到根节点,再将查找路径上所有节点都挂到根节点下
348417

349-
![](https://jihulab.com/xnzone/earth-bear/-/raw/master/find-union-path.jpg)
418+
```c++
419+
// Find "查"操作优化,先找到根节点,再进行"压缩路径"
420+
int Find(int S[], int x) {
421+
int root = x;
422+
// 循环找到根
423+
while (S[root] >= 0) root = S[root];
424+
// 压缩路径
425+
while (x != root) {
426+
// t指向x的父节点
427+
int t = S[x];
428+
// x直接挂到根节点下
429+
S[x] = root;
430+
x = t;
431+
}
432+
// 返回根节点编号
433+
return root;
434+
}
435+
```
436+
437+
350438
351439
- 这样可以让树的高度不超过O($\alpha(n)$)
352440
- O($\alpha(n)$)是一个增长很慢的函数,对于常见的n值,O($\alpha(n)$)通常<=4

0 commit comments

Comments
 (0)