二叉树的遍历、存储、性质、定义——数据结构——day7

树的定义

树的定义:树(Tree)是n(n≥0)个结点的有限集。n=0 时称为空树。在任意一棵非空树中:
(1)有且仅有一个特定的称为根(Root)的结点;
(2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、……、Tm,其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。

在这里插入图片描述

对于树的定义还需要强调两点:
	1.n>0 时根结点是唯一的,不可能存在多个根结点,别和现实中的大树混在一起,现实中的树有很多根须,那是真实的树,数据结构中的树是只能有一个根结点。
	2.m>0时,子树的个数没有限制,但它们一定是互不相交的。像图 中的两个结构就不符合树的定义,因为它们都有相交的子树。

在这里插入图片描述

节点分类

树的结点包含一个数据元素及若干指向其子树的分支。结点拥有的子树数称为结点的度(Degree)。

度为0的结点称为叶结点(Leaf)或终端结点;
度不为0的结点称为非终端结点或分支结点。
除根结点之外,分支结点也称为内部结点。树的度是树内各结点的度的最大值。

在这里插入图片描述

节点间的关系

结点的子树的根称为该结点的孩子(Child),相应地,该结点称为孩子的双亲(Parent)。同一个双亲的孩子之间互称兄弟(Sibling)。
结点的祖先是从根到该结点所经分支上的所有结点。所以对于H来说,D、B、A都是它的祖先。反之,以某结点为根的子树中的任一结点都称为该结点的子孙。

在这里插入图片描述

树的其他相关概念

结点的层次(Level)从根开始定义起,根为第一层,根的孩子为第二层。若某结点在第1层,则其子树的根就在第1+1层。其双亲在同一层的结点互为堂兄弟。显然图中的 D、E、F 是堂兄弟,而G、H、I、J也是。树中结点的最大层次称为树的深度(Depth)或高度,当前树的深度为4。
在这里插入图片描述
如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树。

对比线性表与树的结构

线性结构									 		树结构
第一个数据元素:无前驱				根结点:无双亲,唯一
最后一个数据元素:无后继				叶结点:无孩子,可以多个
中间元素:一个前驱一个后继			中间结点:一个双亲多个孩子

二叉树的遍历

树的创建

/*创建一颗二叉树*/
TREE_NODE *create_Btree()
{
	BTDATA_TYPE data = tree[idx++];
	if (data == '#')
	{
		return NULL;
	}

	TREE_NODE *pnode = malloc(sizeof(TREE_NODE));
	if (NULL == pnode)
	{
		perror("fail malloc");
		return  NULL;
	}
	pnode->data = data;
	pnode->pl = create_Btree();
	pnode->pr = create_Btree();

	return pnode;
}

前序遍历

/*前序遍历一颗二叉树*/
void pre_order(TREE_NODE *proot)
{
	if (NULL == proot)
	{
		return ;
	}
	printf("%c", proot->data);
	pre_order(proot->pl);
	pre_order(proot->pr);
}

中序遍历

/*二叉树的中序遍历*/
void mid_order(TREE_NODE *proot)
{
	if (NULL == proot)
	{
		return ;
	}

	mid_order(proot->pl);
	printf("%c", proot->data);
	mid_order(proot->pr);
}

后序遍历

/*二叉树的后序遍历*/
void pos_order(TREE_NODE *proot)
{
	if (NULL == proot)
	{
		return ;
	}
	
	pos_order(proot->pl);
	pos_order(proot->pr);
	printf("%c", proot->data);
}

获取节点个数

int get_btree_node_cnt(TREE_NODE *proot)
{
	if (NULL == proot)
	{
		return 0;
	}
	return 1+get_btree_node_cnt(proot->pl)+get_btree_node_cnt(proot->pr);
}

获取树的深度

int get_btree_layer_cnt(TREE_NODE *proot)
{
	if (NULL == proot)
	{
		return 0;
	}
	int layL = get_btree_layer_cnt(proot->pl);
	int layR = get_btree_layer_cnt(proot->pr);

	return layL > layR ? layL+1 : layR+1;
}

销毁树

void destroy_btree(TREE_NODE *proot)
{
	if (NULL == proot)
	{
		return ;
	}
	destroy_btree(proot->pl);
	destroy_btree(proot->pr);
	free(proot);
}

层序遍历

void layer_order(TREE_NODE *proot)
{
	QUE_LIST *pque = create_link_queue();
	if (NULL == pque)
	{
		return ;
	}
	
	DATA_TYPE outdata;
	QUE_NODE *pnode = create_node(proot);
	push_queue(pque, pnode);

	while (!is_empty_queue(pque))
	{
		pop_queue(pque, &outdata);
		printf("%c", outdata->data);
		if (outdata->pl != NULL)
		{
			pnode = create_node(outdata->pl);
			push_queue(pque, pnode);
		}
		if (outdata->pr != NULL)
		{
			pnode = create_node(outdata->pr);
			push_queue(pque, pnode);
		}
	}

	destroy_queue(pque);
}

二叉树的性质

二叉树(Binary Tree)是n(n≥0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。
在这里插入图片描述

二叉树特点

二叉树的特点有
■每个结点最多有两棵子树,所以二叉树中不存在度大于 2 的结点。注意不是只有两棵子树,而是最多有。没有子树或者有一棵子树都是可以的。
■左子树和右子树是有顺序的,次序不能任意颠倒。
■即使树中某结点只有一棵子树,也要区分它是左子树还是右子树。

满二叉树

在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
在这里插入图片描述

完全二叉树

对一棵具有 n个结点的二叉树按层序编号,如果编号为i(1<i<n)的结点与同样深度的满二叉树中编号为 i的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。
在这里插入图片描述

二叉树的特点:

(1)叶子结点只能出现在最下两层。
(2)最下层的叶子一定集中在左部连续位置。
(3)倒数二层,若有叶子结点,一定都在右部连续位置。
(4)如果结点度为1,则该结点只有左孩子,即不存在只有右子树的情况。
(5)同样结点数的二叉树,完全二叉树的深度最小。

二叉树的性质

性质1:在二叉树的第i层上至多有2的(i-1)次方个结点(i>1)。
性质2:深度为k的二叉树至多有2*-1个结点(*>1)。
性质3:对任何一棵二叉树 T,如果其终端结点数(叶子节点)为n,度为2的结点数为m,则n=m+1。
性质 4:具有n个结点的完全二叉树的深度为[log2(2为底)n]+1。([x]表示不大于x的最大整数)。

  • 31
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值