一棵树
在計算機科學中，**樹**（英語：）是一种抽象数据类型（ADT）或是實作這種抽象数据类型的数据结构，用來模擬具有樹狀結構性質的数据集合。它是由n（n>0）个有限节点组成一个具有层次关系的集合。把它叫做"树"是因为它看起来像一棵倒挂的树，也就是说它是根朝上，而叶朝下的。它具有以下的特点：

* 每个节点都只有有限个子节点或無子節點；
* 没有父节点的节点称为根节点；
* 每一个非根节点有且只有一个父节点；
* 除了根节点外，每个子节点可以分为多个不相交的子树；
* 樹裡面沒有環路(cycle)

术语
--

1. **节点的度**：一个节点含有的子树的个数称为该节点的度；
2. **树的度**：一棵树中，最大的节点度称为树的度；
3. **叶节点**或**终端节点**：度为零的节点；
4. **非终端节点**或**分支节点**：度不为零的节点；
5. **父亲节点**或**父节点**：若一个节点含有子节点，则这个节点称为其子节点的父节点；
6. **孩子节点**或**子节点**：一个节点含有的子树的根节点称为该节点的子节点；
7. **兄弟节点**：具有相同父节点的节点互称为兄弟节点；
8. 节点的**层次**：从根开始定义起，根为第1层，根的子节点为第2层，以此类推；
9. **深度**：对于任意节点n,n的深度为从根到n的唯一路径长，根的深度为0；
10. **高度**：对于任意节点n,n的高度为从n到一片树叶的最长路径长，所有树叶的高度为0；
11. **堂兄弟节点**：父节点在同一层的节点互为堂兄弟；
12. **节点的祖先**：从根到该节点所经分支上的所有节点；
13. **子孙**：以某节点为根的子树中任一节点都称为该节点的子孙。
14. **森林**：由m（m>=0）棵互不相交的树的集合称为森林；

树的种类
----

有序/无序：
* 无序树：树中任意节点的子节点之间没有顺序关系，这种树称为无序树，也称为自由树。
* 有序树/搜索树/查找树：树中任意节点的子节点之间有顺序关系，这种树称为有序树。即树的所有节点按照一定的顺序排列，这样进行插入、删除、查找时效率就会非常高

平衡/不平衡：
* 平衡树
	+ 绝对平衡树：所有叶节点在同一层
	+ 非绝对平衡树
* 不平衡树

节点的分叉情况：
* 等叉树：是每个节点的键值个数都相同、子节点个数也都相同
	+ 二叉树：每个节点最多含有两个子树的树称为二叉树；
		- 完全二叉树：对于一棵二叉树，假设其深度为d（d>1）。除了第d层外，其它各层的节点数目均已达最大值，且第d层所有节点从左向右连续地紧密排列，这样的二叉树被称为完全二叉树；
			* 满二叉树：所有叶节点都在最底层的完全二叉树；
		- 平衡二叉树（AVL树）：当且仅当任何节点的两棵子树的高度差不大于1的二叉树；
		- 排序二叉树(二叉查找树（英语：Binary Search Tree))：也称二叉搜索树、有序二叉树；
	+ 霍夫曼树：带权路径最短的二叉树称为哈夫曼树或最优二叉树；
	+ 多叉树（英语：）
* 不等叉树：每个节点的键值个数不一定相同、子节点个数也不一定相同
	+ B树：对不等叉树的节点键值数和插入、删除逻辑添加一些特殊的要求，使其能达到绝对平衡的效果。B树全称Balance Tree。如果某个B树上所有节点的分叉数最大值是m，则把这个B数叫做m阶B树。

存储
--

### 父节点表示法

#### 存储结构

|  |  |
| --- | --- |
| 
```
/\* 树节点的定义 \*/
#define MAX\_TREE\_SIZE 100
typedef struct
{
 TElemType data;
 int parent; /\* 父节点位置域 \*/
} PTNode;
typedef struct
{
 PTNode nodes[MAX\_TREE\_SIZE];
 int n; /\* 节点数 \*/
} PTree;

```
 |  |


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| A | 

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| B | 

|  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| E | 

|  |  |
| --- | --- |
|   | H |
|   |
|   | I |
|   |
|   | J |
|   |

 |
|   |

 |
|   |
|   | C |
|   |
| D | 

|  |  |
| --- | --- |
|   | F |
|   |
| G | 

|  |  |
| --- | --- |
|   | K |
|   |

 |
|   |

 |
|   |

 |
|   |

#### 基本操作

设已有链队列类型LinkQueue的定义及基本操作（参见队列）。

##### 构造空树

清空或销毁一个树也是同样的操作

```
void ClearTree(PTree \*T)
{ 
 T->n = 0;
}

```

##### 构造树

```
void CreateTree(PTree \*T)
{ 
 LinkQueue q;
 QElemType p,qq;
 int i=1,j,l;
 char c[MAX\_TREE\_SIZE]; /\* 临时存放孩子节点数组 \*/
 InitQueue(&q); /\* 初始化队列 \*/
 printf("请输入根节点(字符型，空格为空): ");
 scanf("%c%\*c",&T->nodes[0].data); /\* 根节点序号为0，%\*c吃掉回车符 \*/
 if(T->nodes[0].data!=Nil) /\* 非空树 \*/
 {
 T->nodes[0].parent=-1 ; /\* 根节点无父节点 \*/
 qq.name=T->nodes[0].data;
 qq.num=0;
 EnQueue(&q,qq); /\* 入队此节点 \*/
 while(i<MAX\_TREE\_SIZE&&!QueueEmpty(q)) /\* 数组未满且队不空 \*/
 {
 DeQueue(&q,&qq); /\* 节点加入队列 \*/
 printf("请按长幼顺序输入节点%c的所有孩子: ",qq.name);
 gets(c);
 l=strlen(c);
 for(j=0;j<l;j++)
 {
 T->nodes[i].data=c[j];
 T->nodes[i].parent=qq.num;
 p.name=c[j];
 p.num=i;
 EnQueue(&q,p); /\* 入队此节点 \*/
 i++;
 }
 }
 if(i>MAX\_TREE\_SIZE)
 {
 printf("节点数超过数组容量\n");
 exit(OVERFLOW);
 }
 T->n=i;
 }
 else
 T->n=0;
}

```

##### 判断树是否为空

```
Status TreeEmpty(PTree \*T)
{ /\* 初始条件：树T存在。操作结果：若T为空树，则返回TRUE，否则返回FALSE \*/
 return T->n==0;
}

```

##### 获取树的深度

```
int TreeDepth(PTree \*T)
{ /\* 初始条件：树T存在。操作结果：返回T的深度 \*/
 int k,m,def,max=0;
 for(k=0;k<T->n;++k)
 {
 def=1; /\* 初始化本节点的深度 \*/
 m=T->nodes[k].parent;
 while(m!=-1)
 {
 m=T->nodes[m].parent;
 def++;
 }
 if(max<def)
 max=def;
 }
 return max; /\* 最大深度 \*/
}

```

##### 获取根节点

```
TElemType Root(PTree \*T)
{ /\* 初始条件：树T存在。操作结果：返回T的根 \*/
 int i;
 for(i=0;i<T->n;i++)
 if(T->nodes[i].parent<0)
 return T->nodes[i].data;
 return Nil;
}

```

##### 获取第i个节点的值

```
TElemType Value(PTree \*T,int i)
{ /\* 初始条件：树T存在，i是树T中节点的序号。操作结果：返回第i个节点的值 \*/
 if(i<T->n)
 return T->nodes[i].data;
 else
 return Nil;
}

```

##### 改变节点的值

```
Status Assign(PTree \*T,TElemType cur\_e,TElemType value)
{ /\* 初始条件：树T存在，cur\_e是树T中节点的值。操作结果：改cur\_e为value \*/
 int j;
 for(j=0;j<T->n;j++)
 {
 if(T->nodes[j].data==cur\_e)
 {
 T->nodes[j].data=value;
 return OK;
 }
 }
 return ERROR;
}

```

##### 获取节点的父节点

```
TElemType Parent(PTree \*T,TElemType cur\_e)
{ /\* 初始条件：树T存在，cur\_e是T中某个节点 \*/
 /\* 操作结果：若cur\_e是T的非根节点，则返回它的父节点，否则函数值为＂空＂\*/
 int j;
 for(j=1;j<T->n;j++) /\* 根节点序号为0 \*/
 if(T->nodes[j].data==cur\_e)
 return T->nodes[T->nodes[j].parent].data;
 return Nil;
}

```

##### 获取节点的最左孩子节点

```
TElemType LeftChild(PTree \*T,TElemType cur\_e)
{ /\* 初始条件：树T存在，cur\_e是T中某个节点 \*/
 /\* 操作结果：若cur\_e是T的非叶子节点，则返回它的最左孩子，否则返回＂空＂\*/
 int i,j;
 for(i=0;i<T->n;i++)
 if(T->nodes[i].data==cur\_e) /\* 找到cur\_e，其序号为i \*/
 break;
 for(j=i+1;j<T->n;j++) /\* 根据树的构造函数，孩子的序号＞其父节点的序号 \*/
 if(T->nodes[j].parent==i) /\* 根据树的构造函数，最左孩子(长子)的序号＜其它孩子的序号 \*/
 return T->nodes[j].data;
 return Nil;
}

```

##### 获取节点的右兄弟节点

```
TElemType RightSibling(PTree \*T,TElemType cur\_e)
{ /\* 初始条件：树T存在，cur\_e是T中某个节点 \*/
 /\* 操作结果：若cur\_e有右(下一个)兄弟，则返回它的右兄弟，否则返回＂空＂\*/
 int i;
 for(i=0;i<T->n;i++)
 if(T->nodes[i].data==cur\_e) /\* 找到cur\_e，其序号为i \*/
 break;
 if(T->nodes[i+1].parent==T->nodes[i].parent)
 /\* 根据树的构造函数，若cur\_e有右兄弟的话则右兄弟紧接其后 \*/
 return T->nodes[i+1].data;
 return Nil;
}

```

##### 输出树

```
void Print(PTree \*T)
{ /\* 输出树T。加 \*/
 int i;
 printf("节点个数=%d\n",T->n);
 printf(" 节点 父节点\n");
 for(i=0;i<T->n;i++)
 {
 printf(" %c",Value(T,i)); /\* 节点 \*/
 if(T->nodes[i].parent>=0) /\* 有父节点 \*/
 printf(" %c",Value(T,T->nodes[i].parent)); /\* 父节点 \*/
 printf("\n");
 }
}

```

##### 向树中插入另一棵树

```
Status InsertChild(PTree \*T,TElemType p,int i,PTree c)
{ /\* 初始条件：树T存在，p是T中某个节点，1≤i≤p所指节点的度+1，非空树c与T不相交 \*/
 /\* 操作结果：插入c为T中p节点的第i棵子树 \*/
 int j,k,l,f=1,n=0; /\* 设交换标志f的初值为1，p的孩子数n的初值为0 \*/
 PTNode t;
 if(!TreeEmpty(T)) /\* T不空 \*/
 {
 for(j=0;j<T->n;j++) /\* 在T中找p的序号 \*/
 if(T->nodes[j].data==p) /\* p的序号为j \*/
 break;
 l=j+1; /\* 如果c是p的第1棵子树，则插在j+1处 \*/
 if(i>1) /\* c不是p的第1棵子树 \*/
 {
 for(k=j+1;k<T->n;k++) /\* 从j+1开始找p的前i-1个孩子 \*/
 if(T->nodes[k].parent==j) /\* 当前节点是p的孩子 \*/
 {
 n++; /\* 孩子数加1 \*/
 if(n==i-1) /\* 找到p的第i-1个孩子，其序号为k1 \*/
 break;
 }
 l=k+1; /\* c插在k+1处 \*/
 } /\* p的序号为j，c插在l处 \*/
 if(l<T->n) /\* 插入点l不在最后 \*/
 for(k=T->n-1;k>=l;k--) /\* 依次将序号l以后的节点向后移c.n个位置 \*/
 {
 T->nodes[k+c.n]=T->nodes[k];
 if(T->nodes[k].parent>=l)
 T->nodes[k+c.n].parent+=c.n;
 }
 for(k=0;k<c.n;k++)
 {
 T->nodes[l+k].data=c.nodes[k].data; /\* 依次将树c的所有节点插于此处 \*/
 T->nodes[l+k].parent=c.nodes[k].parent+l;
 }
 T->nodes[l].parent=j; /\* 树c的根节点的父节点为p \*/
 T->n+=c.n; /\* 树T的节点数加c.n个 \*/
 while(f)
 { /\* 从插入点之后，将节点仍按层序排列 \*/
 f=0; /\* 交换标志置0 \*/
 for(j=l;j<T->n-1;j++)
 if(T->nodes[j].parent>T->nodes[j+1].parent)
 {/\* 如果节点j的父节点排在节点j+1的父节点之后（树没有按层序排列），交换两节点\*/
 t=T->nodes[j];
 T->nodes[j]=T->nodes[j+1];
 T->nodes[j+1]=t;
 f=1; /\* 交换标志置1 \*/
 for(k=j;k<T->n;k++) /\* 改变父节点序号 \*/
 if(T->nodes[k].parent==j)
 T->nodes[k].parent++; /\* 父节点序号改为j+1 \*/
 else if(T->nodes[k].parent==j+1)
 T->nodes[k].parent--; /\* 父节点序号改为j \*/
 }
 }
 return OK;
 }
 else /\* 树T不存在 \*/
 return ERROR;
}

```

##### 删除子树

```
Status deleted[MAX\_TREE\_SIZE+1]; /\* 删除标志数组(全局量) \*/
void DeleteChild(PTree \*T,TElemType p,int i)
{ /\* 初始条件：树T存在，p是T中某个节点，1≤i≤p所指节点的度 \*/
 /\* 操作结果：删除T中节点p的第i棵子树 \*/
 int j,k,n=0;
 LinkQueue q;
 QElemType pq,qq;
 for(j=0;j<=T->n;j++)
 deleted[j]=0; /\* 置初值为0(不删除标记) \*/
 pq.name='a'; /\* 此成员不用 \*/
 InitQueue(&q); /\* 初始化队列 \*/
 for(j=0;j<T->n;j++)
 if(T->nodes[j].data==p)
 break; /\* j为节点p的序号 \*/
 for(k=j+1;k<T->n;k++)
 {
 if(T->nodes[k].parent==j)
 n++;
 if(n==i)
 break; /\* k为p的第i棵子树节点的序号 \*/
 }
 if(k<T->n) /\* p的第i棵子树节点存在 \*/
 {
 n=0;
 pq.num=k;
 deleted[k]=1; /\* 置删除标记 \*/
 n++;
 EnQueue(&q,pq);
 while(!QueueEmpty(q))
 {
 DeQueue(&q,&qq);
 for(j=qq.num+1;j<T->n;j++)
 if(T->nodes[j].parent==qq.num)
 {
 pq.num=j;
 deleted[j]=1; /\* 置删除标记 \*/
 n++;
 EnQueue(&q,pq);
 }
 }
 for(j=0;j<T->n;j++)
 if(deleted[j]==1)
 {
 for(k=j+1;k<=T->n;k++)
 {
 deleted[k-1]=deleted[k];
 T->nodes[k-1]=T->nodes[k];
 if(T->nodes[k].parent>j)
 T->nodes[k-1].parent--;
 }
 j--;
 }
 T->n-=n; /\* n为待删除节点数 \*/
 }
}

```

##### 层序遍历树

```
void TraverseTree(PTree \*T,void(\*Visit)(TElemType))
{ /\* 初始条件：二叉树T存在,Visit是对节点操作的应用函数 \*/
 /\* 操作结果：层序遍历树T,对每个节点调用函数Visit一次且仅一次 \*/
 int i;
 for(i=0;i<T->n;i++)
 Visit(T->nodes[i].data);
 printf("\n");
}

```

### 孩子链表表示法

#### 存储结构

```
/\*树的孩子链表存储表示\*/
typedef struct CTNode { // 孩子节点
 int child;
 struct CTNode \*next;
} \*ChildPtr;
typedef struct {
 ElemType data； // 节点的数据元素
 ChildPtr firstchild； // 孩子链表头指针
} CTBox;
typedef struct {
 CTBox nodes[MAX\_TREE\_SIZE]；
 int n, r； // 节点数和根节点的位置
} CTree;

```


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| A | 

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| B | 

|  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| E | 

|  |  |
| --- | --- |
|   | H |
|   |
|   | I |
|   |
|   | J |
|   |

 |
|   |

 |
|   |
|   | C |
|   |
| D | 

|  |  |
| --- | --- |
|   | F |
|   |
| G | 

|  |  |
| --- | --- |
|   | K |
|   |

 |
|   |

 |
|   |

 |
|   |

森林、树与二叉树的转换
-----------

见二叉树相应章节

外部链接
----

* （中文）树-数据结构(Python)by EINDEX
* Data Structures and Algorithm Analysis in C (2nd edition) （页面存档备份，存于）

参考文献
----


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
算法 |
| --- |
|  |
| 排序 | 

|  |  |
| --- | --- |
| 比较排序 | 
* 冒泡排序
* 选择排序
* 插入排序
* 希尔排序
* 快速排序
* 归并排序
* 堆排序
* 鸡尾酒排序
* 梳排序
* 侏儒排序
* 图书馆排序
* 内省排序
* 奇偶排序

 |
|  |
| 线性时间排序 | 
* 鸽巢排序
* 基数排序
* 計數排序
* 桶排序

 |
|  |
| 并行排序 | 
* 排序网络（英语：）
* Batcher归并网络

 |
|  |
| 不实用的 | 
* Bogo排序
* 臭皮匠排序

 |
|  |
| 图 | 
* 拓撲排序

 |

 |
|  |
| 搜索 | 

|  |  |
| --- | --- |
| 列表 | 
* 线性搜索
* 二分搜索
* 插值搜尋

 |
|  |
| 树・图 | 
* 广度优先搜索
	+ 最良優先搜索（英语：）
	+ 均一开销搜索
	+ A\*
* 深度优先搜索
	+ 迭代深化深度优先搜索
	+ 深度限制搜索（日语：）
	+ 双向搜索
* 分枝限定法（英语：）

 |
|  |
| 字符串 | 
* KMP算法
* 博耶-穆尔字符串搜索算法
* AC自动机算法
* 拉宾-卡普算法
* bitap算法

 |

 |
|  |
| 最短路问题 | 
* 戴克斯特拉算法
* 贝尔曼-福特算法
* A\*搜尋演算法
* Floyd-Warshall算法

 |
|  |
| 最小生成树 | 
* 普林姆算法
* 克鲁斯克尔演算法

 |
|  |
| 最大流最小割 | 
* 福特-富尔克森算法
* 埃德蒙兹-卡普算法
* 迪尼茨算法

 |
|  |
| 线性规划 | 
* 单纯形法
* 卡马卡尔算法（英语：）

 |
|  |
| 順序統計量 | 
* 选择算法
* 中位数的中位数（英语：）

 |
|  |
| 種類 | 
* 精确算法
* 近似算法
* 随机化算法

 |
|  |
| 其他 | 
* 分治法
* 动态规划
* 贪心算法

 |
|  |
| **Category:算法** |

 |

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
计算机科学中的树 |
| --- |
|  |
| 二叉树 | 
* 二元搜尋樹
* 笛卡尔树
* MVP树
* Top tree（英语：）
* T树
* 线索二叉树

 |
|  |
| 自平衡二叉查找树 | 
* AA树
* AVL树
* 左倾红黑树
* 红黑树
* 替罪羊树
* 伸展树
* 树堆
* 加权平衡树

 |
|  |
| B树 | 
* B+树
* B\*树
* Bx树
* UB树
* 2-3树
* 2-3-4树
* (a,b)-树
* 跳舞樹（英语：）
* H树

 |
|  |
| 堆 | 
* 二叉堆
* 二项堆
* 斐波那契堆
* 左偏树
* 配对堆
* 斜堆
* 范恩德蟒蛇樹（英语：）

 |
|  |
| Trie | 
* 后缀树
* 基数树
* 三叉查找树
* X-快速前缀树
* Y-快速前缀树
* AC自动机

 |
|  |
| 二叉空间分割（BSP）树 | 
* 四叉树
* 八叉树
* *k*-d树
* 隐式*k*-d树
* VP树

 |
|  |
| 非二叉树 | 
* 指数树（英语：）
* 融合树（英语：）
* PQ树（英语：）
* SPQR树（英语：）

 |
|  |
| 空间数据分割树 | 
* R树
* R\*树
* R+树
* X树
* M树
* 線段樹 (儲存區間)
* 线段树 (区间查询)
	+ 可持久化线段树
* 希尔伯特R树
* 优先R树

 |
|  |
| 其他树 | 
* 散列日历
* 散列树
* 手指樹（英语：）
* 顺序统计树
* 度量樹（英语：）
* 覆蓋樹（英语：）
* BK树
* 二重連鎖樹（英语：）
* iDistance（英语：）
* Link-cut tree（英语：）
* Log-structured merge-tree（英语：）
* 树状数组
* 哈希树

 |

 |

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
数据结构 |
| --- |
|  |
| 类型 | 
* 集合
* 容器

 |
|  |
| 抽象类型 | 
* 关联数组
	+ 多重关连数组（英语：）
* 列表
* 堆栈
* 队列
	+ 双端队列
* 优先队列
	+ 双端优先队列
* 集合
	+ 多重集
	+ 併查集
* 可持久化数据结构
	+ 线段树

 |
|  |
| 数组 | 
* 字串
* 位数组
* 环形缓冲器
* 动态数组
* 哈希表
* 哈希数组树（英语：）
* 稀疏矩阵

 |
|  |
| 链（英语：） | 
* 关联表（英语：）
* 链表
* 跳跃列表
* 松散链表（英语：）
* 异或链表

 |
|  |
| 树 | 
* 线段树
* 自平衡二叉查找树
* B树
* 二叉树
	+ AA树
	+ AVL树
	+ 红黑树
	+ 平衡树
	+ 伸展树
	+ 二叉查找树
* 堆
	+ 二叉堆
	+ 左偏树
	+ 二项堆
	+ 斐波那契堆
* R树
	+ R\*树
	+ R+树
	+ 希爾伯特R树（英语：）
* 希尔伯特前缀树
	+ 哈希树

 |
|  |
| 图 | 
* 有向图
* 有向无环图
* 二元决策图
* 无向图
* 确定性非循环有限自动机（英语：）

 |
|  |
| 数据结构术语 |

 |