数据结构 详细介绍树

第一节 树的基本概念和术语
一、引言
树形结构是一类重要的非线性数据结构,树中结点之间具有明确的层次关系,并且结点之间有分支,非常类似于真正的树。树形结构在客观世界中大量存在,如行政组织机构和人类社会家谱等都可以用树形结构形象表示。

二、树的定义
1、树Tree 是n(n>=)个结点的有限集T,n=0时称为空树,任意非空树
(1)有且仅有一个特定的称为根(Root)的结点。
(2)n>1时,除根结点外的其余结点可分为m(m>=0)个互不交互的子集T1,T2…Tm,其中每个子集本身又是一颗树,并称为根的子树(Subtree)
2、从逻辑上看,树型结构具有以下特点:
(1)任何非空树中有且仅有一个结点没有前驱结点,这个结点就是树的根结点
(2)除根结点之外,其余所有结点有且仅有一个直接前驱结点
(3)包括根结点在内,每个结点可以有多个直接后继结点。
(4)树形结构是一种具有递归特征的数据结构
(5)树形结构中的数据元素之间存在的关系通常是一对多,或者多对一的关系
在这里插入图片描述
在这里插入图片描述
(1)结点的度:结点所拥有的子树的个数。A的度3,E的度2
(2)树的度:树中结点度的最大值。
(3)叶子:度为0的结点
(4)分支结点:度不为0的结点。除根结点之外的分支结点统称为内部结点。根结点又称为开始结点
(5)孩子:结点的直接后继(结点的子树的根)
(6)双亲:结点直接前趋
(7)兄弟:同一双亲的孩子互为兄弟
(8)子孙:一颗树上的任何结点称为根的子孙
(9)祖先:从根结点开始到该及诶点连线上的所有结点都是该结点的祖先
(10)路径:树中存在一个结点序列k1,k2…ki,使得ki是ki+1的双亲(1《i<j),则称该及诶点序列是从k1到kj的一条路径或道路
即链接两个结点的线段的数目等于j-1;
注意:
若一个结点序列是路径,则在树的树形图表示中,该结点序列’自上而下‘地通过路径上的每条边。
(11)结点的层:设跟结点的层数为1,其余结点的层数等于双亲结点的层数加1。
(12)输的高度(或深度):树中所有结点层数的最大值。
(13)有序树和无序树:将树中每个结点的各子树看成是从左到右有次序的(即不能互换),则称该树为有序树;否则称为无序树。
(14)森林:是m(m>=0)棵互不相交的树的集合。树和森林的概念相近,删去一棵树的根,就得到一个森林;反之加上一个节点做为根,森林变成一棵树。

11.26
五、树的性质
性质一: 非空树中的结点总数等于树中所有结点的度之和加1.
证明:
根据树的定义,在一颗树中除根结点以外,每个结点有且仅有一个双亲结点,即每个结点与指向它的一个分支结点一一对应,因而除了树的根结点之外的结点数等于树中所有结点的分支数(度数),由此可得知树中的结点总数应为所有结点的度数之和加1.
性质二:度为k的非空树的第i层最多有k的(i-1)次方个结点(i>=1);
性质三:深度为h的k叉树最多有k^h - 1/k-1个结点。
证明:
显然,只有当深度为h的k叉树商的每一层都达到该层最大结点总数时,该树的结点总数将达到最大,因此有:
k的一次方一直加到k的(h-1)次方等于k的h次方-1比上k-1
证毕

真题选解
已知在一颗含有n个结点的树中,只有度为k的分支结点和度为0的叶子结点,该树中含有叶子结点的数目为______.

答案:((k-1)n+1)/ k
解析:设度为k的分支结点数为
nk,度为0的叶子结点数为n0,数中总分支数为B.除根结点之外,其他每个结点都有且仅有一个进入支,而这些进入支是由度为k的结点发出的,度为k的结点总共发出k
nk个分支。显然有:
nk=n-no
B=n-1
B=k*nk
得nk=(n-1)/k
得n0=((k-1)*n+1)/k
(暂时未理解)

第二节
二叉树
一、二叉树的定义和性质
1、二叉树的定义
二叉树(Binary Tree)是n(n>=0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的、分别称作这个根的左子树和右子树的二叉树组成。这是一个递归定义。

2.二叉树的五种基本形态
二叉树可以是空集;根可以有空的左子树或右子树;或者左,右树皆为空。二叉树的五种基本形态:

在这里插入图片描述
3.二叉树与树的关系
(1)二叉树与无序树不同
二叉树中,每个结点最多只能由两棵子树,并且有左右之分。
二叉树并非是树的特殊情形,它们呢是两种不同的数据结构。

(2)二叉树与度数为2的有序树不同
在有序树中,虽然一个结点的孩子之间是有左右次序的,但是若该结点只有一个孩子,就无线区分其左右次序。而在二叉树中,即使是一个孩子也有左右之分。
在这里插入图片描述

真题选解
下列陈述中正确的是()。
A.二叉树是度为2的有序树
B.二叉树中结点只有一个孩子时无左右之分
C.二叉树中必有度为2的结点
D.二叉树中最多只有两棵子树,并且有左右之分

我觉得选D

4.二叉树的性质
性质一:二叉树第i(i>=1)层最多有2^(i-1)个结点。
证明:用数学归纳法:
(1)当i=1时,有2^(i-1)=1.因为第一层上只有一个根节点,所以命题成立。
(2)假设对所有的j(1<=j<i)命题成立,即第j层上之多有2^(j-1)个结点
(3)根据归纳假设,第i-1蹭上至多有2^(i-2)个结点。由于二叉树的每个结点至多有两个孩子,故第i层商的节点数至多是第i-1层商的最大结点数的二倍。即j=1时,该层商至多有2 * 2 ^(i-2)= 2 ^(i-1)个结点,故成立。

性质二:深度为k(k>=1)的二叉树,最多有2^(k-1)个结点。
证明:在具有相同深度的二叉树中,仅当每一层都含有最多结点数时,其数中结点数最多。因此利用性质1可得,深度为k的二叉树的节点数至多为:
2^0 +2 ^1+…2 ^(k-1)=2 ^k -1
故命题正确。

性质三:任意非空二叉树中,若叶节点的数目为n0,度为2的结点数目为n2,则有关系n0=n2+1.
证明:
设度为1的结点数目为n1,二叉树的结点总数为n,有n=n0+n1+n2
设B表示分支数,具有n个结点的二叉树的分支总数为n-1.择有B=n-1
而所有这些分支不是来自于度为1的结点就是来自于度为2的结点,即每一个度为1的结点发出一个分支,每一个度为2 的结点发出两个分支。于是有
B=n1+2n2
联立上面三个等式可以到的
n0=n2+1

真题选解
假定在一颗二叉树中,双分支结点数为15个,单分支结点数为30个,则也节点数为(16)个;
根据二叉树的性质,叶结点数n0与度为2的节点数n2的关系式n0=n2+1

满二叉树:一颗深度为k且有2^k-1个结点的二叉树称为满二叉树。
在这里插入图片描述

满二叉树的特点:
(1)每一层商的节点数都达到最大值。即对给定高度,它是具有最多节点数的二叉树。满二叉树的结点总数一定是奇数。
(2)满二叉树中不存在度数为1的结点,每个分支结点具有两棵高度相同的子树,且叶节点都在最下一层上。

例:求具有n个结点的满二叉树叶结点数n0和度为2的节点数n2分别是多少。
根据二叉树的性质三,有n0=n2+1
没有度为1的结点:n=n0+n2
联立上面两个等式可得:n0=(n+1)/2 n2=(n-1)/2

完全二叉树:
若一棵二叉树至多只有最下面的两层上节点数的度数可以小于2,并且最下一层上的结点都集中在该层最左边的若干位置上,则此二叉树称为完全二叉树。

深度为k的完全二叉树所含叶结点的个数最多情况,一定是满二叉树的情况,即第k层上具有最多结点的情况。根据二叉树的性质1,第k层上最多有2^(k-1)个结点。位于第k层数的结点,均为叶结点。

性质4:具有n个结点的完全二叉树的深度为k=[log(2,n)]+1
向下取整或者log(2,(n+1))向上取整
证明:设所求完全二叉树的深度为k。由于完全二叉树定义可得:
深度为k的完全二叉树的前k-1层时深度为k-1的满二叉树,一共有2^(k-1)-1个结点。
由于完全二叉树深度为k,故第k层商还有若干个结点,因此该完全二叉树的结点个数:
n>2^(k-1)-1
另一方面,由性质2可得:
n<=2^k-1
即:2 ^(k-1)- 1 <n<=2 ^k-1
由此可推出:2^(k-1)<= n<2 ^k,取对数后有:
k-1<=long2n<k
又因为k-1和k是相邻的两个整数,故有k=[log(2,n)]+1 (向下取整)

真题选解
一棵含18个结点的二叉树的高度至少为(c)
A.3 b.4 C.5 D.6

解析:二叉树高度k=log(2,18)向下取整+1=5。
例若根结点的层数为1,则具有n个结点的二叉树最大高度是(a)
A.n
B.log(2,n)向下取整
C.log(2,n)向下取整+1
D.n/2
解析:具有n个结点的二叉树是单支树时,高度最大为n.具有n个结点二叉树最小高度log(2,n)向下取整+1。

性质五:
如果将一颗有n个结点的完全二叉树按层从1开始编号,则对任一编号为i(1<=i<=n)的结点X有:
若i=1,则结点X是跟;若i>1,则X的双亲的编号为i/2向下取整
若2i>n;则结点X无左孩子(且无右孩子);否则,X的左孩子编号为2i
若2i+1>n,则结点X无右孩子;否则,X的右孩子的编号为2i+1.
在这里插入图片描述

选择题:
将一棵有50个结点的完全二叉树按层从1开始编号,则对编号为25的结点x,该结点()。
A.无左右孩子 B.有左孩子,无右孩子
C.有右孩子,无左孩子 D.有左右孩子
B
解析:由二叉树的性质五可知,若结点ai有左孩子,则其左孩子的编号为2i,若其右孩子的编号为2i+1.显然编号为25的结点左孩子编号为50,右孩子编号为51.但该完全二叉树只有50个结点,最大编号为50,所以有左孩子,无右孩子

计算题:
求具有n个结点的完全二叉树叶结点数n0为多少?
根据二叉树的性质五,该具有n个结点的完全二叉树的分支结点中编号UI大的结点的编号为n/2向下取整。所以该完全二叉树分支结点数为n/2向下取整,则也结点数n0=n-n/2向下取整=n/2向上取整。(没懂,跟满二叉树要区分)

二.二叉树的存储结构
1、顺序存储结构
(1)完全二叉树的顺序存储
在这里插入图片描述
性质五修改为:
如果将一棵有n个结点的完全二叉树按层从0开始编号,则任一编号
为i(0<=i<n)的结点X有:
若i=0,则结点X是跟;若i>0,则X的双亲编号为(i-1)/2向下取整。
若2i+1<n,则结点X的左孩子编号为2i+1,否则,结点X无左孩子(且无右孩子)。
若2i+2<n,则结点X的右孩子的编号为2i+2,否则,X无右孩子

(2)一般二叉树的顺序存储

2、链式存储结构
(1)二叉链结点结构
lchild data rchild

说明:
(1)数据域data,用以存放元素值
(2)指针域lchild和rchild,分别指向该结点的左孩子和右孩子。
没有左孩子是lchild=NULL,没有右孩子是rchild=NULL

在这里插入图片描述

当二叉树有n个结点是,其二叉链表上公有2n个指针域,其中只有n-1个指针域用于存放其左、右孩子的指针(n个结点的二叉树一共有n-1个分支),剩下的n+1个指针域为空。

(2)二叉链结点类型定义
typedef struct node
{
DataType datal
Struct node *lchild,*rchild; //左右孩子指针
}BinTNode; //结点类型
typedef BinTNode *BinTree; //BinTree为指向bintNode类型结点的指针类型

(3)三叉链结点结构
lchild data parent rchild

说明:增加的parent域指向其双亲

画出所示的二叉树的三叉链表表示图
在这里插入图片描述
三叉链表结构与二叉链表结构的区别是它的结点多了一个指向双亲的指针域,当二叉树有n个结点时,其三叉链表上共有3n个指针域,其中只有n-1个指针域用于存放其左右孩子的指针,有n-1个指向双亲的,剩下n+2个指针域为空。

第三节 二叉树的运算
一、
1.按广义表表示二叉树结构生成二叉链表的算法。
在这里插入图片描述
(A(B(D(E,F)),C))

算法中用了一个指针数组来模拟栈存储结点的双亲指针,根据读入广义表中的字符分为四种不同情况进行处理:
算法描述

BinTNod * CreateTree(char *str)
{
//str为存储广义表的字符串指针
BinTNode *str[100]; //用指针数组模拟栈
BinTNode *p= NULL;
int top,k,j=0;
top = -1; //置空栈
char ch=str[j];
BinTNode *b=NULL;
while(ch!=’\0’)
{
switch(ch)
{

	 	case'(':top++;st[top]=p;k=1;break;
		
		  case')':top--;breakk

			case',':k=2;break;
			
			default:p=(BinTNode*)malloc(sizeof(BinTNode));
				p->data=ch;
				p->lchild=p->rchild=NULL;
				if(b==NULL)
				b=p;
				else
				{
					switch(k)
						{
							case 1:st[top]->lchild= p;break;
							case 2:st[top]->rchild =p;break;
						}
				}
	}
		j++;ch=str[j];
}
return  b;

}

在这里插入图片描述
算法思想 :
首先对一般的二叉树添加若干个虚结点,使其称为完全二叉树,然后依次输入结点信息,若输入的结点不是虚结点’@’,则建立一个新结点,若是第一个结点,则令其为根结点,否则将新结点作为左孩子或右孩子连接到它的双亲结点上。如此重复下去,直到输入结束符号#时位置
算法描述
在这里插入图片描述
在这里插入图片描述

二、二叉树的遍历
遍历:是指演着某条搜索路径周游二叉树,依次对树中的每个结点访问且仅访问一次。

遍历方案
从二叉树的递归定义可知,一颗非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上可以按某种次序执行三个操作:
1.访问根结点本身(D)
2.遍历跟结点的左子树(L)
3.遍历根结点的右子树(R)

以上三种操作有六种执行次序:
DLR(根左右)/ LDR(左根右) / LRD(左右根)
DRL(根右左) / RDL(右根左) / RLD(右左根)
注意:前三种次序与后三种次序对称,故讨论先左后右的前三种次序。

1、递归遍历算法
三种遍历的递归定义:
(1)先序遍历DLR(根左右):也叫先根遍历,若二叉树非空,则依次执行如下操作:
a.访问根结点
b.遍历左子树
c.遍历右子树
(2)中序遍历LDR(左根右):也叫中跟遍历,若二叉树非空,则依次执行如下操作:
a.遍历左子树
b.访问根结点
c.遍历右子树
(3)后序遍历LRD(左右根):也叫后根遍历,若二叉树非空,则依次执行如下操作:
a.遍历左子树
b.遍历右子树
c.访问根结点
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
GCFABD

三种遍历的算法
忘记抄录了

第四节

线索二叉树

一、线索二叉树的概念
1、定义
n个结点的二叉链表中含有n+1个空指针域。利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前驱和后继结点的指针(这种附件的指针称为“线索”)。

2、线索链表的结点结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、二叉树线索化算法

1、算法思想

按某种次序遍历二叉树,在遍历过程中用线索取代空指针即可
(1)如果根结点的左孩子指针域为空,则将左线索标志域置1,同时给根结点加左线索
(2)如果根结点的右孩子指针域为空,则将右线索标志域置1,同时给根结点加右线索
(3)将根结点指针赋给存放前驱结点指针的变量,以便当访问下一个结点时,此跟结点作为前趋结点。

2、二叉链表加中序线索的算法

算法与中序遍历算法类似,只是将遍历算法中访问根结点bt的操作改为在bt和中序前驱*pre之间建立线索。
在这里插入图片描述

三、二叉线索链表上的运算

1、在中序线索二叉树商查找某结p的后继结点
分析:
两种情况:
(1)若结点
P的rtag值域为1,则表明p->rchild 为右线索,它直接指向结点。
(2)若结点p的rtag值域为0,则表明p->rchild指向右孩子结点,结点P的中序后继结点必是其右子树第一个中序遍历到的结点,因此从结点p的右孩子开始,沿左指针链向下查找,直到找到一个没有左孩子的结点为止,该结点是结点p的右子树中“最左下”的结点,它就是结点*p的中序后继结点。

在这里插入图片描述

2、线索二叉树的中序遍历算法

基本思想 首先从根结点起沿左指针链向下查找,直到找到一个左线索标准为1的结点为止,该结点的左指针域必为空,它就是整个中序序列中的第一个结点。访问该结点,然后就可以依次找结点的后继,直到中序后继为空时为止。

在这里插入图片描述
在这里插入图片描述

第五节

森林和树

一.树的存储结构

1、双亲表示法
在这里插入图片描述

在双亲表示法中,每个存储结点由两个域组成,数据域一一存储树上结点的数据元素;双亲域一一存储双亲结点在结点数组中的下标值。

在这种表示法下,求直到结点的祖先很方便,但求直到结点的子孙则不方便。

2、孩子链表表示法

孩子链表表示法的基本思想是:为树上的每个结点X建立一个“孩子链表”,存储X中的数据元素和指向X的所有孩子的指针。一个孩子链表是一个带头结点的单链表,单链表的头结点含两个域:数据域和指针域。其中数据域用于存储结点X中的数据元素;指针域用于存放指向该单链表中第一个表结点的指针;

为了检索方便,所有头结点组织成一个数组,称为表头数组,对每个结点X的孩子链表来说,其中的所有表结点也含有两个域,孩子与和指针域。第i个表结点的孩子域存储X的第i个孩子在头结点数组中的下标值。

在这里插入图片描述
3、孩子兄弟表示法
孩子兄弟表示法又称二叉链表表示法,孩子兄弟表示法中所有存储结点的形式相同,均含三个域:数据域一一存储树上结点的数据元素:孩子域一一存放指向本结点第一个孩子的指针;兄弟域一一存放指向本结点下一个兄弟的指针。

在这里插入图片描述

二、树、森林与二叉树的转换

1、树。森林转换为二叉树
将一棵树转换为二叉树可以按一下步骤进行:
(1)在所有相邻兄弟结点之间分别加一条连线
(2)对每个分支结点,除了其最左孩子外,删去该结点与其他孩子结点的连线
(3)以根结点为轴心,顺时针旋转45°

注意:由树转换的二叉树的根结点的右孩子始终为空,原因是树的根结点不存在兄弟结点,下图给出例子实现这一转换过程。

在这里插入图片描述
(2)森林转换为二叉树
将森林转换为二叉树的步骤可以归纳如下:
1.分配将树邻中的每棵树转换为二叉树;
2.从最后那棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树的根结点的右孩子,直到所有二叉树全部链接,这样得到的二叉树的根结点就是树林中第一棵输的根结点。

在这里插入图片描述
在这里插入图片描述
a

(3)二叉树转换为树
将一颗二叉树转换为树可以按下列步骤进行:
1.若某结点是双亲结点的左孩子,则将该节点的右孩子以及当且仅当连续地沿着此右孩子的右子树方向不断地搜索到所有右孩子,都分别与该节点得到双亲结点用虚线链接起来
2.删去原二叉树中所有的双亲结点与其右孩子的连线
3.将图形规整化,使个结点按层次排序,并且将虚线改成实线

(4)二叉树转为森林
步骤
1.去掉二叉树的右子树,将去掉右子树后剩下的二叉树转换为一棵树
2.将在第一步中被去掉的右子树再执行第一步
3.重复前两部,知道转换完成
在这里插入图片描述

三、树和森林的遍历

1、树的遍历
(1)树的前序遍历定义:a.访问根结点 b.依次前序遍历根的各子树
(2)树的后序遍历定义:a.依次后序遍历根的各子树 b.访问根结点r

写出如图所示树的前序遍历和后序遍历的序列和该树对应二叉树的前序遍历,中序遍历和后序遍历序列

在这里插入图片描述
树的前序遍历序列:ABEFGCHDIJ
树的后序遍历序列:EFGBHCIJDA

二叉树的前序遍历序列:ABEFGCHDIJ
二叉树的中序遍历序列:EFGBHCIJDA(这个不容易理解)
二叉树的后序遍历序列:GFEHJIDCBA

注意
a.前序遍历一棵树恰好等于前序遍历该树对应二叉树
b.后序遍历一棵树恰好等于中序遍历该树对应二叉树

2.森林的遍历
(1)前序遍历
若森林非空,则:
a.访问森林中第一个棵树的根结点;
b.前序遍历第一棵树中根结点的各个字数所构成的森林
c.前序遍历除第一棵树外其他树构成的森林。

(2)后序遍历森林
若森林非空,则:
a.后序遍历森林中第一课树的根结点的各个子树所构成的森林;
b.访问第一课树的根结点
c.后序遍历除第一棵树外其他树构成的深林
在这里插入图片描述
??注意二叉树b结点下面的都在右子树所以先访问b

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值