上个星期,z老师跳过队列讲了树= =
所以我们先写数据结构中关于树的一小部分知识
先康康树的样子:
随意介绍一下 : A 就是这个树的根节点,GHIJ是这个树的叶子节点
然后
这个图就不是树,它是什么呢
回答:森林(只有两颗树的森林)
然后介绍了和树有关的相关概念
树 : 树是由结点或顶点和边组成的(可能是非线性的)且不存在着任何环的一种数据结构。没有结点的树称为空(null或empty)树。一棵非空的树包括一个根结点,还(很可能)有多个附加结点,所有结点构成一个多级分层结构。
节点的度 : 节点所拥有的子树的数目
叶子结点 : 度为0的节点
树的度 : 树种各个节点的度的最大值
孩子节点 : 节点的字数的根称为孩子节点
父节点(双亲节点) : 该结点是孩子结点的父节点(双亲节点)(听起来像是废话)
兄弟节点 : 就是同一个父节点(双亲节点)的孩子节点之间互称兄弟节点
祖先节点 : 从根节点到孩子节点所经分支上的所有节点都称为祖先结点
子孙节点 : 节点子树中的所有节点
树的层次 :从根节点开始,根节点为第一层,根的子节点为第二层,以此类推
树的深度 : 树层次的最大值
有序树 : 各个子树是从左到右的,不能互换的
森林 : m颗互不相交的树的集合
okey
接下来讲一下线性表和树的对比;(注意表述方法)
线性表的第一个数据没有前驱 , 树的根节点没有父节点(双亲节点)
线性表的中间元素有一个前驱元素和一个后继元素 ,树的中间节点有一个父节点(双亲结点)多个孩子节点
完了讲建树,有两种方法
(一)双亲表示法
这张图讲的是双亲表示法,r表示根节点的数组下标,这里指的是A,n表示节点个数,这里有7个,分别是ABCDEFG
具体解释一下图里那个表格的意思,就是数据域data和父节点域parent,也就是:
B的父节点在数组下标为0的位置,
C的父节点在数组下标为0的位置,
D的父节点在数组下标为0的位置,
E的父节点在数组下标为2的位置,
F的父节点在数组下标为2的位置,
G的父节点在数组下标为5的位置
然后根据数据描述(就是当具有包含关系的数据的输入之后,数据被存储成上图表格中的形式,被抽象成图中树的样子)我们可以得出双亲表示法建树的存储方式为:
typedef struct Snode //结点结构
{
ElemType data;//这里指的char类型,因为data域存储的是ABCD
int parent;//父节点下标
}PNode;
typedef struct //树结构
{
PNode tnode[MAX_SIZE]; //树の数组
int n; //结点个数
}PTree;
然后是对树进行的基本操作,除了和线性表类似的 数据的插入,删除,修改,查找等等,树还应该要有统计树的层数、树的节点个数、返回叶子节点的个数之类的一些特殊的功能
这里就放最重要的生成树的代码吧,(毕竟博客名字写的就是树的两种生成方式)
//结点个数和对应的data及parent下标
//10
//
//R -1
//A 0
//B 0
//C 0
//D 1
//E 1
//F 3
//G 6
//H 6
//K 6
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 20
typedef char ElemType;
typedef struct Snode
{
ElemType data;
int parent;
}PNode;
typedef struct
{
PNode tnode[MAX_SIZE];
int n;
}PTree;
PTree InitPNode(PTree tree)
{
int i, j;
char ch;
printf("请输入节点个数:\n");
scanf("%d", &(tree.n));
printf("请输入结点的值其双亲位于数组中的位置下标:\n");
for (i = 0; i < tree.n; i++)
{
getchar();
scanf("%c %d", &ch, &j);
tree.tnode[i].data = ch;
tree.tnode[i].parent = j;
}
return tree;
}
void PrintTree(PTree tree)
{
for (int i = 0; i < tree.n; i++) {
int ad = tree.tnode[i].parent;
printf("NODE : %c ; PARENT : %c ; INDEX : %d\n", tree.tnode[i].data, tree.tnode[ad