数据结构【第七天】:树(一)

基本概念

定义:

树( Tree)是 n(n>=0) 个结点的有限集。n=0时称为空树。在任意一棵非空树中:

1.有且仅有一个特定的称为根 (Root)的结点; 

2.当 n>1 时,其余结点可分为 m (m>O) 个互不相变的有限集 T1 、T2、……、Tm ,其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。

性质:

1.n>0时根节点是唯一的;不存在多个根节点;

2.m>0时子树的个数没有限制,但是他们一定是互不相交的。

结点分类

结点的度:该结点拥有的子树的数目

终端结点(叶结点):结点度为0的结点

分支结点(非终端结点):度不为0

内部结点:除根以外的分支结点

树的度:树内各节点的度的最大值

图为转载

结点间关系

结点的子树的根称为该节点的孩子,相应的该结点称为孩子的双亲,同一个双亲的孩子之间互称兄弟,结点的祖先是从根到该节点所经分支上的所有结点,以某结点为根的子树中的任一结点都称为该结点的子孙

其他概念

结点层次:从根开始定义,根为第一层,根的孩子为第二层,依次递加

树的深度(高度):树中结点的最大层次

有序树:蜀中结点的各子树看成是从左至右有次序,不可互换的。否则称为无序树

森林:m(m>=0)棵互不相交的树的集合

树的抽象类型

ADT 树(tree)

Data 

    树是由一个根结点和若干棵子树构成 。 树中结点具有相同数据类型及层次关系。

Operation

    lnitTree ( *T) ;  //构造空树T

    DestroyTree ( *T );  //销毁树T

    CreateTree(*T,definition);  //按definition中给出树的定义来构造树

    ClearTree(*T);  //若树T存在,清空树T

    TreeEmpty(T);  //若树为空树,返回true,否则返回false

    TreeDepth(T);  //返回T的深度

    Root(T);  //返回T的根结点

    Value(T,cur_e);  //cur_e为树中的一个结点则返回该结点值

    Assign(T,cur_e,value);  //给树T的结点cur_e赋值value

    Parent(T,cur_e);  //若cur_e是树T的非根结点,则返回他的双亲,否则返回false

    LeftChild(T,cur_e);  //若cur_e是树T的非叶结点,则返回它的最左孩子,否则返回空

    RightSibling(T,cur_e);  //若cur_e有右兄弟,则返回其右兄弟,否则返回空

    InsertChild(*T,*p,i,c);  //其中p指向树T的某个结点,i为所指结点p的度加上1,非空树c与T不相交

                                       //操作将插入c为树T中p指结点的第i棵子树

    DeleteChild(*T,*p,i);  //其中p指向树T的某个结点,i为所指结点p的度,操作结果为删除T中p所指结点的第i棵子树

endADT

树的存储结构

一、双亲表示法

每个结点中包含一个数据域和一个指示器。

指示器指示其双亲结点到链表中的位置,结合数组存储即为其双亲结点的下标,根结点的双亲位置设为-1

结构定义

#define MAX_TREE_SIZE 100
typedef int TElemType;    //树结点的数据类型,暂定为整型
typedef struct PTNode    //结点结构
{
    TElemType data;    //结点数据
    int parent;        //双亲位置
}PTNode;

typedef struct    //树结构
{
    PTNode nodes[MAX_TREE_SIZE];    //结点数组
    int r,n;    //根的位置 和 结点数
}
数组下标dataparent
0A-1
1B0
2C0
3D1
4E2
5F2
6G3
7H3
8I3
9J4

 

 

 

 

以上结构在于不容易找到结点的孩子,必须遍历整个结构才行,所以在以上基础进行改进。

改进一:增加一个指针域,指向该结点最左边的孩子,若没有孩子则设为-1

数组下标dataparentfirstchild
0A-1-1
1B03
2C04
3D16
4E29
5F2-1
6G3-1
7H3-1
8I3-1
9J4-1

 

 

 

 

改进二:再增加一个指针域,指向该结点的右兄弟,如果没有右兄弟则设为-1

数组下标dataparentfirstchildrightsib
0A-1-1-1
1B032
2C04-1
3D16-1
4E295
5F2-1-1
6G3-17
7H3-18
8I3-1-1
9J4-1-1

 

 

 

 

该存储结构可以根据需求不断增减指针域来符合设计要求。

二、孩子表示法

每个结点有多个指针域,其中每个指针指向一棵子树的根结点,我们把这种方法叫做多重链表表示法。

但是由于每个结点的度不同,指针域的大小也不同,故存在一些问题。

最终常采用方法结合顺序结构和链表结构,详细如下:

把每个结点的孩子结点排列起来,以单链表作存储结构,则n个结点有n个孩子链表,如果是叶子结点则此链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构存进一个一维数组。

结构定义

#define MAX_TREE_SIZE 100
typedef struct CTNode    //孩子结点
{
    int child;        //数据域
    struct CTNode *next;    //下一个孩子(即该结点兄弟)位置
}*ChildPtr;

typedef struct        //表头结构
{
    TElemType data;    //数据域
    ChildPtr firstchild;      //该结点第一个孩子  
}CTBox;

typedef struct        //树结构    
{
    CTBox nodes[MAX_TREE_SIZE];    //结点数组
    int r,n;        //根的位置和结点数
}CTree

以上结构还是存在不知道结点双亲的情况,所以可以改进,在表头结点中加入parent指针域,结合之后称为双亲孩子表示法

三、孩子兄弟表示法

任意一棵树,他的结点的第一个孩子如果存在就是唯一的,他的右兄弟存在也是唯一的。因此可以设置两个指针,分别指向该节点的第一个孩子和他的右兄弟。

结构定义

typedef struct CSNode
{
    TElemType data;
    struct CSNode *firstchild,*rightsib;
}CSNode,*CSTree;

同样如果有必要完全可以再增加一个parent指针,指向其双亲的位置。

而上述图的结构即为二叉树

注:以上图片均为转载网络图片

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值