数据结构——二叉树

一、二叉树定义:

二叉树是n个结点的有限集合,该集合或者为空(空二叉树)、或者由一个根结点及两个不相交的、被分别称为左子树和右子树的二叉树组成

特殊二叉树

(1)斜树:所有的结点都只有左子树的二叉树叫左斜树。所有的结点都只有右子树的二叉树,叫右斜树,两者统称为斜树

(2)满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树叫做满二叉树

(3)完全二叉树:对一棵具有n个结点的二叉树按层序编号,如果编号为i(1≤i≤n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树

满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树

二、二叉树的性质: 

(1)在二叉树的第i层上至多有2^{i-1}个结点(i>=1)

(2)深度为k的二叉树至多有2^{k}-1个结点

(3)对于任何一个二叉树T,如果其终端结点数为n_{0},度为2的结点数为n_{2},则n_{0} =  n_{2}-1

(4)具有n个结点的完全二叉树的深度为[log_{2}n]+1

(5)对于一棵有n个结点的完全二叉树(其深度为[log_{2}n]+1),其结点按层序编号,每层从左到右,对任意一个结点i(1<=i<=n)有:

                       <1>如果i=1,则结点i是二叉树的根,无双亲;如果I > 1,则其双亲结点是[i / 2]

                       <2>如果2i > n,则结点i无左孩子(结点i为叶子节点);否则其左孩子是结点2i

                       <3>如果2i  + 1> n,则结点无右孩子;否则其右孩子是2i + 1

三、二叉树的存储结构:

        由于二叉树的特殊性,我们可以用顺序存储结构来实现,就是用一维数组来存储二叉树的结点,并且结点的存储位置,也就是数组的下标要能体现结点之间的逻辑关系。

        对一般二叉树,层序编号不能反映逻辑关系,但是可以将其按完全二叉树编号,只不过把不存在的结点设置为“^”,但是考虑一种极端情况,一棵深度为k的右斜树,它只有k个结点,但是要分配2𝑘−1个结点,显然是对空间的浪费。

        所以,顺序存储结构一般只适用于完全二叉树。

二叉树的每个结点最多有两个孩子,所以设计一个数据域和两个指针域是比较合适的,我们称这样的链表叫做二叉链表

//二叉树的二叉链表结点结构定义
typedef char ElemType;
typedef struct BiTNode			//结点结构
{
	ElemType data;
	struct BiTNode* lchild;		//左孩子指针
	struct BiTNode* rchild;		//右孩子指针
}BiTNode,*BiTree;

 四、遍历二叉树:

(1)前序遍历:先访问根结点,然后前序遍历左子树,再前序遍历右子树

//二叉树的前序遍历递归算法
void PreOrderTraverse(BiTree T)
{
	if (T == NULL)
	{
		return;
	}
	printf("%c ", T->data);		//显示结点数据
	PreOrderTraverse(T->lchild);	//遍历左子树
	PreOrderTraverse(T->rchild);	//遍历右子树
}

(2)中序遍历:从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后访问根结点,最后中序遍历右子树

//二叉树的中序遍历递归算法
void InOrderTraverse(BiTree T)
{
	if (T == NULL)
	{
		return;
	}
	InOrderTraverse(T->lchild);
	printf("%c ", T->data);
	InOrderTraverse(T->rchild);
}

(3)后序遍历:从左到右先叶子后结点的方式遍历访问左右子树,最后访问根结点

		//二叉树的后续遍历递归算法
		void PostOrderTraverse(BiTNode* T)
		{
			if (T == NULL)
			{
				return;
			}
			PostOrderTraverse(T->lchild);
			PostOrderTraverse(T->rchild);
			printf("%c ", T->data);
		}

(4)层序遍历:从根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问

 对于以上二叉树:

前序遍历:ABDEHCFG

中序遍历:DBHEAFCG

后序遍历:DHEBFGCA

层序遍历:ABCDEFGH

二叉树遍历的性质:

        已知前序遍历序列和中序遍历序列,可以唯一确定一棵二叉树

        已知后序遍历序列和中序遍历序列,可以唯一确定一棵二叉树

五、二叉树的建立:

        如果我们要建立左图这样的树,为了能让每个结点确认是否有左右孩子,我们对它进行了扩展,如右图所示,也就是将二叉树中每个结点的空指针引出一个虚结点,其值为#。我们称这种处理后的二叉树为原二叉树的扩展二叉树。

扩展二叉树就可以做到一个遍历序列确定一棵二叉树,如上图前序遍历序列就是:AB#D#C##

假设二叉树的结点均是一个字符

//按前序输入二叉树中结点的值创建二叉树
void CreateBiTree(BiTree* T)
{
	ElemType ch;
	scanf("%c", &ch);
	if (ch == '#')
		*T = NULL;
	else
	{
		*T = (BiTree)malloc(sizeof(BiTNode));
		if (!*T)
			exit(1);
		(*T)->data = ch;
		CreateBiTree(&(*T)->lchild);
		CreateBiTree(&(*T)->rchild);
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值