1
0
mirror of https://github.com/Didnelpsun/CS408.git synced 2026-02-10 14:15:53 +08:00

更新树

This commit is contained in:
Didnelpsun
2021-04-27 23:26:10 +08:00
parent 018a10d0bc
commit 78e41abe7f
4 changed files with 187 additions and 6 deletions

View File

@@ -141,6 +141,7 @@
<ItemGroup>
<ClCompile Include="head.h" />
<ClCompile Include="main.c" />
<ClCompile Include="sequence_tree.h" />
<ClCompile Include="sequence_stack.h" />
<ClCompile Include="sequence_tree.cpp" />
<ClCompile Include="thread_tree.h" />

View File

@@ -118,4 +118,73 @@ int LevelorderTraversalLinkTree(LinkTree tree, int(*visit)(LinkTree elem)) {
EnterSequenceQueue(&queue, p->rchild);
}*/
}
}
// 二叉排序树遍历查找
LinkTreeNode* TraversalSearchBST(LinkTree tree, element_type elem) {
while (tree != NULL && elem != tree->data) {
if (elem < tree->data) {
tree = tree->lchild;
}
else {
tree = tree->rchild;
}
}
return tree;
}
// 二叉排序树递归查找
LinkTreeNode* RecursiveSearchBST(LinkTree tree, element_type elem) {
if (tree == NULL) {
// 为空树
return NULL;
}
if (elem = tree->data) {
return tree;
}
else if (elem < tree->data) {
return RecursiveSearchBST(tree->lchild, elem);
}
else {
return RecursiveSearchBST(tree->rchild, elem);
}
}
// 二叉排序树递归插入
int InsertBST(LinkTree tree, element_type elem) {
if (tree == NULL) {
tree = (LinkTree)malloc(sizeof(LinkTree));
if (tree) {
tree->data = elem;
tree->lchild = tree->rchild = NULL;
return 0;
}
else {
printf("BSTInsert:插入分配空间失败!");
return 1;
}
}
// 关键词重复
else if (elem == tree->data) {
printf("BSTInsert:关键字重复!");
return 1;
}
else if (elem < tree->data) {
return InsertBST(tree->lchild, elem);
}
else {
return InsertBST(tree->rchild, elem);
}
}
// 根据关键字建立二叉排序树
int CreateBST(LinkTree tree, element_type elem[], int n) {
tree = NULL;
int i = 0;
while (true)
{
InsertBST(tree, elem[i]);
i++;
}
return 0;
}

View File

@@ -1,6 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "head.h"
// 定义一个顺序树数组
typedef int SequenceTree[MAXSIZE];

View File

@@ -178,6 +178,123 @@
3. 若小于根结点,则在左子树上查找,否则在右子树上查找。
4. 遍历结束后仍没有找到则返回NULL。
遍历查找的时间复杂度是$O(\log_2n)$,则递归查找的时间复杂度是$O(\log_2n+1)$,其中$\log_2n+1$代表二叉树的高度。
查找成功的平均查找长度ASL二叉树的平均查找长度为$O(\log_2n)$,最坏情况是每个结点只有一个分支,平均查找长度为$O(n)$。
#### 二叉排序树的插入
+ 若原二叉排序树为空,就直接插入结点。
+ 否则,若关键字小于根结点值,插入左结点树。
+ 若关键字大于根结点值,插入右结点树。
#### 二叉排序树的删除
+ 搜索到对应值的目标结点。
+ 若被删除结点1p是叶子结点则直接删除不会破坏二叉排序树的结构。
+ 若被删除结点只有一棵左子树或右子树,则让该结点的子树称为该结点父结点的子树,来代替其的位置。
+ 若被删除结点有左子树和右子树,则让其结点的直接后继(中序排序该结点后一个结点,其右子树的最左下角结点)或直接前驱(中序排序该结点前一个结点,其左子树的最右下角结点)替代该结点,并从二叉排序树中删除该的结点直接后继后直接前驱,这就变成了第一种或第二种情况。
### 平衡二叉树
即AVL树树上任意一结点的左子树和右子树的高度之差不超过1。
结点的平衡因子=左子树高-右子树高。
在插入一个结点时,查找路径上的所有结点都可能收到影响。
从插入点往回(从下往上)找到第一个不平衡的结点,调整以该结点为根的子树。每次调整的对象都是最小不平衡树。
### 调整最小不平衡树
#### 从结点的左孩子的左子树中插入导致不平衡
```terminal
A(2)
|
-----------
| |
B(1) AR(H)
|
------------
| |
BL(H+1) BR(H)
```
由于在结点A的左孩子B的的左子树BL上插入了新结点A的平衡因子由1变成了2导致以A为根的子树失去了平衡需要进行一次向右的旋转操作。
将A的左孩子B向右上旋转代替A成为根节点将A结点向右下选择为成B的右子树的根结点而B的原右子树则作为A结点的左子树。
```terminal
B(0)
|
-----------
| |
BL(H+1) A(0)
|
------------
| |
BR(H) AR(H)
```
#### 从结点的右孩子的右子树中插入导致不平衡
```terminal
A(-2)
|
-----------
| |
AL(H) B(-1)
|
------------
| |
BL(H) BR(H+1)
```
由于在结点A的右孩子(R)的右子树(R)上插入了新结点A的平衡因子由-1减至-2导致以A为根的子树失去平衡需要一-次向左的旋转操作。
将A的右孩子B向左上旋转代替A成为根结点将A结点向左下旋转成为B的左子树的根结点而B的原左子树则作为A结点的右子树。
```terminal
B(0)
|
-----------
| |
A(0) BR(H+1)
|
------------
| |
AL(H) BR(H)
```
#### 从结点的左孩子的右子树中插入导致不平衡
```terminal
A(2)
|
-----------
| |
B(1) AR(H)
|
------------
| |
BL(H) BR(H+1)
```
```terminal
B(0)
|
-----------
| |
BL(H+1) A(0)
|
------------
| |
BR(H) AR(H)
```
#### 从结点的右孩子的左子树中插入导致不平衡
## 树与森林
### 树的存储结构