mirror of
https://github.com/Didnelpsun/CS408.git
synced 2026-02-10 14:15:53 +08:00
更新树
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "head.h"
|
||||
|
||||
// 定义一个顺序树数组
|
||||
typedef int SequenceTree[MAXSIZE];
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
#### 从结点的右孩子的左子树中插入导致不平衡
|
||||
|
||||
## 树与森林
|
||||
|
||||
### 树的存储结构
|
||||
|
||||
Reference in New Issue
Block a user