⑴ 数据结构--树和森林
一、 树的定义:
树(tree)是n(n>0)个节点的有限集,在任意一棵树中,(1)有且仅有一个特定的称为根(root)的节点,(2)当n>1时,其余节点可分为m(m>0)个互不相交的有限集,而每个集合本身又是一棵树,称为根的子树(subtree)。
从上面树的定义中可以看到,这是一个递归的定义,即树的定义中又用到了树的概念。
树具有下面两个特点:
(1) 树的根结点没有前驱结点,除根结点外的其他结点有且只有一个前驱结点
(2) 树中所有结点可以有0个或多个后继结点
根据这两个特点,可以看出下图表示的都不是树。
森林(forest)是m(m≥0)棵互不相交的树的集合。任何一棵树,删除了根结点就变成了森林。
二、 树的存储结构
1、 双亲表示法
树中每个结点都有唯一一个双亲结点,根据这一特性,可以用一组连续的存储空间(一维数组)存储树中的各个结点,数组中每个元素都表示树中的一个结点,数组元素为结构体类型,这个结构体类型由结点本身的数据和结点的双亲在数组中的序号组成。
树的双亲表示法对于寻找双亲和根的操作很方便,但是要求某结点的孩子结点,就需要遍历整个数组,而且也不能反映各兄弟之间的关系,因此找到某结点的兄弟也很困难。
2、 孩子表示法
按如下图所示的形式存储。主体是一个与结点个数一样大小的一维数组,数组的每个元素有两个域,一个域用于存放结点数据,另一个用于存放指针,该指针指向由该结点孩子组成的单链表的首位置。单链表的结构也由两个域组成,一个存放孩子结点在一维数组中的序号,另一个为指针域,指向下一个孩子。
孩子表示法中查找双亲很困难,适用于查找孩子的操作。
3、 双亲孩子表示法
双亲孩子表示法是将双亲表示法和孩子表示法结合起来的方法。如下图所示,将各节点的孩子结点组成单链表,用一维数组顺序存储树的结点,数组元素包括结点本身的数据,该结点的孩子结点链表的头指针,存储该结点的双亲在数组中的序号。
4、 孩子兄弟表示法
这种方法的结构体包含:每个结点的数据,指向该结点的第一个孩子结点的指针和指向下一个兄弟结点的指针。
三、 树转换为二叉树
第一步:在树中所有兄弟结点间加一条连线
第四步:调整位置
五、 二叉树转换为树、森林
七、 森林的遍历
森林的遍历分为两种:前序遍历和中序遍历
1、 前序遍历
A. 访问森林中第一棵树的根节点
B. 前序遍历第一棵树的根节点的子树
C. 前序遍历去掉第一棵树后剩余的森林
上图按照前序遍历,结果为:A B C D E F G H J I K
2、 中序遍历
A. 中序遍历第一棵树的根节点的子树
B. 访问森林中第一棵树的根结点
C. 中序遍历去掉第一棵树剩余的森林
上图按照中序遍历,结果为:B A D E F C J H K I G
⑵ 层次模型中的几个术语,什么是根结点,双亲结点,兄弟结点,叶结点
在自己上面没有更高一级的节点,自己这个节点就叫根节点,层次模型是一个目录树,只有一个根节点。双亲节点也叫父节点,相对于当前的节点而言,它的上层节点就叫做父节点。当前节点下面已经没有其他任何节点了,当前的这个节点就叫做叶节点,是最底层的节点。
在层次模型中,每个结点表示一个记录类型,记录类型之间的联系用结点之间的连线(有向边)表示,这种联系是父子之间的一对多的联系。这就使得层次数据库系统只能处理一对多的实体联系。
每个记录类型可包含若干个字段,这里记录类型描述的是实体,字段描述实体的属性。每个记录类型及其字段都必须命名。各个记录类型、同一记录类型中各个字段不能同名。每个记录类型可以定义一个排序字段,也称码字段,如果定义该排序字段的值是唯一的,则它能唯一地标识一个记录值。
一个层次模型在理论上可以包含任意有限个记录类型和字段,但任何实际的系统都会因为存储容量或实现复杂度而限制层次模型中包含的记录类型个数和字段个数。
在层次模型中,同一双亲的子女结点称为兄弟结点,没有子女结点的结点称为叶结点在层次模型中,同一双亲的子女结点称为兄弟结点,没有子女结点的结点称为叶结点。
⑶ 数据结构双亲表示法一个问题,有帮助必定采纳!!!
⑷ 哈夫曼树中共有99个结点,则该树中有___个叶子结点;若采用二叉链表作为存储结构,则该树中有___个空指针域
50个叶子结点,51个空指针。因为是二叉链表,就是孩子兄弟表示法,不是一般的二叉树那样画,要转化一下。
在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码。
反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。
(4)双亲存储最新消息扩展阅读:
为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上。
显然字使用频率越小权值越小,权值越小叶子就越靠下,于是频率小编码长,频率高编码短,这样就保证了此树的最小带权路径长度效果上就是传送报文的最短长度。
动态哈夫曼编码使用一棵动态变化的哈夫曼树,对第t+1个字符的编码是根据原始数据中前t个字符得到的哈夫曼树来进行的,编码和解码使用相同的初始哈夫曼树,每处理完一个字符,编码和解码使用相同的方法修改哈夫曼树/
所以没有必要为解码而保存哈夫曼树的信息。编码和解码一个字符所需的时间与该字符的编码长度成正比,所以动态哈夫曼编码可实时进行。
⑸ ml树怎么保存
树有三种常用的存储方式:
双亲表示法、孩子表示法、孩子兄弟表示法。
双亲表示法在存储树的结点时,包括结点值data和该结点的双亲parent,使用一组连续的存储单元存储树的每一个结点及结点间的关系。存储结点的双亲时并不存储其值,存储的是其下标,对于根结点,因为没有双亲,所以设置parent=-1。
该方法的实现分为两部分,一部分是用data域来存储树的每一个结点值,用FirstChild域来存储该结点第一个孩子结点的地址;另一部分是用指针链串起来的其他孩子结点。
孩子兄弟表示法又被称为二叉树表示法,每个结点包含3个部分,即结点值data,指向该节点第一个孩子结点FirstChild,指向该结点的兄弟结点的NextSibling。
⑹ 所有双亲结点是什么意思
双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
二叉树相关术语
树的结点:包含一个数据元素及若干指向子树的分支;
孩子结点:结点的子树的根称为该结点的孩子;
双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;
祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙
结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;
树的深度:树中最大的结点层
结点的度:结点子树的个数
树的度: 树中最大的结点度。
叶子结点:也叫终端结点,是度为 0 的结点;
分枝结点:度不为0的结点;
有序树:子树有序的树,如:家族树;
无序树:不考虑子树的顺序;
⑺ 以二叉链表为存储结构,如何编写算法求二叉树中结点x的双亲
如下代码是通过算法的方式求父节点,其中二叉树的创建是先序方式,如abd##e##c##x0dx0ax0dx0a#include "stdlib.h"x0dx0atypedef int Element;x0dx0astruct Treex0dx0a{ x0dx0a Element data;x0dx0a struct Tree *left; x0dx0a struct Tree *right;x0dx0a};x0dx0ax0dx0avoid CreateBinSortTree(struct Tree **t);x0dx0avoid InsertNode2Tree(struct Tree **root, Element num);x0dx0avoid PrintTree(struct Tree *r, int order);x0dx0astruct Tree *FindParent(struct Tree *r, char ch);x0dx0ax0dx0aint main(int argc, char* argv[])x0dx0a{x0dx0a printf("请输入一组字母(#表示子树为空)\n");x0dx0a struct Tree *t=NULL;x0dx0a CreateBinSortTree(&t);x0dx0a printf("\n根左右:");x0dx0a PrintTree(t,1);x0dx0a printf("\n左根右:");x0dx0a PrintTree(t,2);x0dx0a printf("\n左右根:");x0dx0a PrintTree(t,3);x0dx0a printf("\n");x0dx0a char ch='a'x0dx0a getchar();//获取前次输入回车符x0dx0a printf("请输入节点数据值");x0dx0a scanf("%c",&ch);x0dx0a struct Tree *temp = FindParent(t,ch);x0dx0a if (temp!=NULL)x0dx0a {x0dx0a printf("其父节点数据值为:%c",temp->data);x0dx0a }x0dx0a elsex0dx0a {x0dx0a printf("找不到父节点");x0dx0a }x0dx0a return 0;x0dx0a x0dx0a}x0dx0avoid CreateBinSortTree(struct Tree **t)x0dx0a{ x0dx0a char ch;x0dx0a ch = getchar(); x0dx0a if (ch == '#') x0dx0a { x0dx0a *t = NULL; x0dx0a return ; x0dx0a }x0dx0a *t = (struct Tree *)malloc(sizeof(struct Tree)); x0dx0a (*t)->data = ch;x0dx0a CreateBinSortTree( &((*t)->left)); x0dx0a CreateBinSortTree( &((*t)->right));x0dx0a x0dx0a}x0dx0ax0dx0avoid PrintTree(struct Tree *r, int order)x0dx0a{ x0dx0a if (r == NULL) x0dx0a { x0dx0a return ; x0dx0a }x0dx0a switch(order)x0dx0a { x0dx0a case 1: x0dx0a printf("%c ",r->data);x0dx0a PrintTree(r->left,order); x0dx0a PrintTree(r->right,order); x0dx0a break;x0dx0a case 2: x0dx0a PrintTree(r->left,order); x0dx0a printf("%c ",r->data); x0dx0a PrintTree(r->right,order); x0dx0a break; x0dx0a case 3: x0dx0a PrintTree(r->left,order); x0dx0a PrintTree(r->right,order); x0dx0a printf("%c ",r->data); x0dx0a break; x0dx0a }x0dx0a}x0dx0ax0dx0astruct Tree *FindParent(struct Tree *r, char ch)x0dx0a{x0dx0a if (r==NULL)x0dx0a {x0dx0a return NULL;x0dx0a }x0dx0a if (r->left != NULL)x0dx0a {x0dx0a if (r->left->data == ch)x0dx0a {x0dx0a return r;x0dx0a }x0dx0a }x0dx0a if (r->right != NULL)x0dx0a {x0dx0a if (r->right->data == ch)x0dx0a {x0dx0a return r;x0dx0a }x0dx0a }x0dx0a struct Tree *t=FindParent(r->left,ch);x0dx0a if (t != NULL)x0dx0a {x0dx0a return t;x0dx0a }x0dx0a t = FindParent(r->right,ch);x0dx0a return t;x0dx0a}
⑻ 大自然的主动进化,双亲DNA计算机功能遗传进化方程,婚姻法进化
双亲DNA计算机是一种生物遗传下一代的计算机,通过遗传密码碱基序列排列组合进行十,一,X,÷数学逻辑运算,进行牛顿的微积分,三维空间细胞数学定位计算,时间坐标第四维空间时间坐标细胞分裂分化的精确数学定位计算。这种计算速度极快,父亲精子内DNA计算机数据有一百万亿个细胞定位,母亲卵子内DNA计算机细胞定位有一百万亿个微分方程定位,一分为二,合二为一父母DNA计算机一百万亿个微分方程共同联合计算下一代三维空间四维空间时间坐标上每一个细胞定位GpS数学定位计算防止癌细胞自由错乱。一百万亿个微分方程,有一个微分方程计算差错导致下一代未来的癌细胞扩散?
⑼ 顺序存储表示法为什么不是树的存储形式
顺序存储表示法是树的存储形式的原因:顺序存储方式不仅能用于存储线性结构,还可以用来存放非线性结构,例如完全二叉树是属于非线性结构,但其最佳存储方式是顺序存储方式。
对于一般的家谱树(一般的多叉树)来说,我们可以很清楚的看出层次关系,树的层数表示代数(一共多少代人),树的最后一层表示最后一代人,由于多叉链表法表示的不方便,因此被迫无奈采用孩子兄弟表示法(二叉链表法)。
结构
二叉树的顺序存储就是用一组连续的存储单元存放二又树中的结点元素,一般按照二叉树结点自上向下、自左向右的顺序存储。使用此存储方式,结点的前驱和后继不一定是它们在逻辑上的邻接关系,非常适用于满二又树和完全二又树。根据完全二叉树和满二叉树的特性,假设将图1中的完全二又树存放在一维数组bree中,将发现结点的编号正好与数组元素的下标对应。
⑽ 双亲存储结构
19 for(i=0;i<Max;i++) {
20 sf("%c,%d",&Ptree[i].data,&Ptree[i].parent);
21 getchar();
22 }
23
24 char ch;
25 pf("请输入要查找双亲的节点:");
26 sf("%c",&ch);
27 for(i=0;i<Max;i++)
28 {
29 if(Ptree[i].data==ch)
30 if(Ptree[i].parent==-1)
31 pf("是树根 ");
32 else
33 pf("该节点的双亲是:%c ",Ptree[Ptree[i].parent].data);
34 }
主要问题出在输入数据时, 未能按预期存入数据。 在scanf的参数中加入"&”, 同时getchar();
会将回车从输入流中取出, 以 免其存入数组中。
还有打印双亲时, 要用%c而不是%d.