数据机构之树和森林

树和森林

一、树和森林的定义和性质

1、树的定义

树是n个结点的有限集合。
  树可以为空树,即结点数为零。并且任意一颗非空树有以下特点:
  1. 有且仅有一个根结点;
  2. 当树的结点数大于1时,其余结点可分为多个结点的有限集合,这些集合的每一个又是一棵树,因此为根结点的子树。

2、树中的相关术语

假如有一棵树如下图所示:

这里写图片描述
  祖先结点:从根节点到某个节点的路径上的所有节点都是该结点的祖先结点。比如L结点对应的 从根结点的路径是:A->B->E->L,因此A,B,E都是L的祖先结点。根节点没有祖先结点,它是所有结点的祖先。
  子孙结点:子孙结点和祖先结点相对应,以某个结点为根结点的子树中的结点都是该结点的子孙结点。对应上面的路径,B,E,L都是A结点的子孙结点,树中所有结点(除根节点)都是根节点的子孙结点。
  结点的度:树中一个结点的子结点的个数。比如上述树中B的度是2,因为他有E,F两个子结点,A结点的度是3…
  树的度:树中结点最大度数。上述树的度为3.
  分支结点:度数大于0的结点。
  终端结点:又称叶子结点,度为0的结点,上述树的叶子结点为F,G,H,I,J,K,L。
  结点的层次:从根结点开始数,根结点的层次为1,比如L的层次为4.
  结点的深度:从根节点开始自顶向下逐层累加的。
  结点的高度:从叶结点开始自底向上逐层累加的。
  树的高度:又称深度,是树中结点的最大层数。上述树的高度是4。
  有序树:树中的结点的子树从左到右是由次序的不能交换。
  无序树:树中的结点没有次序可以交换。

3、树的性质

  • 树中结点数等于所有结点的度数加1;
  • 度为m的树第i层上至多m^(i-1)个结点;
  • 高度为h的m叉树至多有(m^h-1)/(m-1)个结点;
  • 具有n个结点的m叉树的最小高度为(取上限(log_m(n(m-1)+1)))。

4、森林的定义

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

二、树的存储结构

树的存储结构包括双亲表示法,孩子表示法,孩子兄弟表示法。

1、双亲表示法

双亲表示法:采用一维连续线性表存储,为每个结点增设一个伪指针,也就是数组中的下标指示其双亲在数组中的位置。

比如下图中根结点的下标为0,其伪指针为-1。

这里写图片描述

双亲表示法的存储结构描述:

    typedef int ElemType;
    #define MAX_SIZE 100
    typedef struct
    {
    	ElemType data;						//数据
      	int parent;							//祖先指针
    }PTNode;
    typedef struct
    {
    	PTNode nodes[MAX_SIZE];
      	int n;								//结点数目
    }PTree;

2、孩子表示法

孩子表示法:每个结点的孩子结点都用链表链接起来组成一个线性结构
这里写图片描述

孩子表示法的结构定义:

    #define MAX_SIZE 100
    typedef int ElemType;
    typedef struct PNode
    {	
    	int son;					//孩子结点的下标
      	struct PNode* next;			//下一个孩子结点
    }PNode;
    
    typedef struct TNode
    {
    	ElemType data;
      	PNode* child;				//孩子结点的指针
    }PTree[MAX_SIZE];

3、孩子兄弟表示法

孩子兄弟表示法:又称二叉树表示法,孩子兄弟表示法有三部分内容:结点数据,指向第一个孩子的指针和指向下一个兄弟的指针。

这里写图片描述
  孩子兄弟表示法的结构定义:

    typedef int ElemType;
    typedef struct CNode
    {
    	ElemType data;
      	struct CNode* firstChild, *nextChild;
    }CNode,* CTree;

三、树的相关操作

1、树、森林和二叉树的转换

树转换为二叉树的规则是:每个节点左指针指向它的第一个孩子结点,右指针指向它的相邻的兄弟结点,故表示为“左孩子右兄弟”。

这里写图片描述

森林转化为二叉树的规则和树转换为二叉树的规则相似:先将森林中的每一棵树转化为二叉树,再将第一棵树作为转化后的二叉树的根,第一棵树的坐姿树作为转化后的二叉树的左子树,第二课二叉树作为二叉树的右子树,第三棵二叉树作为转化后的二叉树的根的右子树的右子树。
这里写图片描述

从根节点开始,若右孩子存在,则把与右孩子结点的连线删除。再查看分离后的二叉树,若其根节点的右孩子存在,则连线删除…。直到所有这些根节点与右孩子的连线都删除为止。将每棵分离后的二叉树转换为树。

这里写图片描述

2、遍历

树的遍历分为先根遍历和后根遍历。

先根遍历:若树非空,则先访问根结点,再从左到右顺序遍历根结点的每一棵子树。

后根遍历:若树非空,则先从左到右顺序遍历根结点的每一棵子树,再访问根结点。

森林的遍历分为先序遍历和中序遍历。

先序遍历:若森林为非空,则先序遍历第一棵树,在先序遍历剩下的树构成的森林。

中序遍历:若森林为非空,则中序遍历第一棵树的根节点的子树森林,再访问第一棵树的根结点,再中序遍历除去第一棵树剩余的树构成的森林。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值