㈠ 二叉树是什么
二叉树 (binary tree) 是另一种树型结构,它的特点是每个结点至多只有二棵子 树 (即二叉树中不存在度大于 2的结点 ),并且,二叉树的子树有左右之分,其次序不能任意颠倒 . 二叉树是一种数据结构 :
Binary_tree=(D,R)
其中: D是具有相同特性的数据元素的集合 ;若 D等于空 ,则 R等于空称为空的二叉树 ;若 D等于空则 R是 D上某个二元关系 H的集合,即 R={H},且
(1) D 中存在唯一的称为根的元素 r,它的关系 H下无前驱 ;
(2) 若 D-{r}不等于空,则 D-{r}={Dl,Dr},且 Dl交 Dr等于空 ;
(3) 若 Dl不等于空 ,则在 Dl中存在唯一的元素 xl,〈 r,xl〉属于 H,且存在 Dl上的关系 Hl属于 H; 若 Dr不等于空 ,则在 Dr中存在唯一的元素 xr,〈 r,xr〉 >属于 H, 且存 Dr上的关 系 Hr属于 H; H={r,xl,< r,xr> ,Hl, Hr};
(4) (Dl, Hl) 是一棵合本定义的二叉树,称为根 r的左子树 ,(Dr,Hr)是一棵符合定义的二叉树,称为根的右子树。
其中,图 6.2 是各种形态的二叉树 .
(1) 为空二叉树 (2)只有一个根结点的二叉树 (3)右子树为空的二叉树 (4)左子树为空的二叉树 (5)完全二叉树
二叉树的基本操作:
(1)INITIATE(BT ) 初始化操作。置 BT为空树。
(2)ROOT(BT)\ROOT(x) 求根函数。求二叉树 BT的根结点或求结点 x所在二叉树的根结点。
若 BT是空树或 x不在任何二叉树上,则函数值为 “空 ”。
(3)PARENT(BT,x) 求双亲函数。求二叉树 BT中结点 x的双亲结点。若结点 x是二叉树 BT 的根结点
或二叉树 BT中无 x结点,则函数值为 “空 ”。
(4)LCHILD(BT,x) 和 RCHILD(BT,x) 求孩子结点函数。分别求二叉树 BT中结点 x的左孩 子和右孩子结点。
若结点 x为叶子结点或不在二叉树 BT中,则函数值为 “空 ”。
(5)LSIBLING(BT,x) 和 RSIBING(BT,x) 求兄弟函数。分别求二叉树 BT中结点 x的左兄弟和右兄弟结点。
若结点 x是根结点或不在 BT中或是其双亲的左 /右子树根 ,则函树值 为 “空 ”。
(6)CRT_BT(x,LBT,RBT) 建树操作。生成一棵以结点 x为根,二叉树 LBT和 RBT分别为左, 右子树的二叉树。
(7)INS_LCHILD(BT,y,x) 和 INS_RCHILD(BT,x) 插入子树操作。将以结点 x为根且右子树为空的二叉树
分别置为二叉树 BT中结点 y的左子树和右子树。若结点 y有左子树 /右子树,则插入后是结点 x的右子树。
(8)DEL_LCHILD(BT,x) 和 DEL-RCHILD(BT,x) 删除子树操作。分别删除二叉树 BT中以结点 x为根的左子树或右子树。
若 x无左子树或右子树,则空操作。
(9)TRAVERSE(BT) 遍历操作。按某个次序依此访问二叉树中各个结点,并使每个结点只被访问一次。
(10)CLEAR(BT) 清除结构操作。将二叉树 BT置为空树。
5.2.2 二叉树的存储结构
一 、顺序存储结构
连续的存储单元存储二叉树的数据元素。例如图 6.4(b)的完全二叉树 , 可以向量 (一维数组 ) bt(1:6)作它的存储结构,将二叉树中编号为 i的结点的数据元素存放在分量 bt[i]中 ,如图 6.6(a) 所示。但这种顺序存储结构仅适合于完全二叉树 ,而一般二叉树也按这种形式来存储 ,这将造成存 贮浪费。如和图 6.4(c)的二叉树相应的存储结构图 6.6(b)所示,图中以 “0”表示不存在此结点 .
二、 链式存储结构
由二叉树的定义得知二叉树的结点由一个数据元素和分别指向左右子树的两个分支构成 ,则表 示二叉树的链表中的结点至少包含三个域 :数据域和左右指针域 ,如图 (b)所示。有时 ,为了便于找 到结点的双亲 ,则还可在结点结构中增加一个指向其双亲受的指针域,如图 6.7(c)所示。
5.3 遍历二叉树
遍历二叉树 (traversing binary tree)的问题, 即如何按某条搜索路径巡访树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。 其中常见的有三种情况:分别称之为先 (根 )序遍历,中 (根 )序遍历和后 (根 )序遍历。
5.3.1 前序遍历
前序遍历运算:即先访问根结点,再前序遍历左子树,最后再前序遍历右子树。前序遍历运算访问二叉树各结点是以根、左、右的顺序进行访问的。例如:
按前序遍历此二叉树的结果为: Hello!How are you?
proc preorder(bt:bitreprtr)
if (bt>null)[
print(bt^);
preorder(bt^.lchild);
preorder(bt^.rchild);]
end;
5.3.2 中序遍历
中序遍历运算:即先中前序遍历左子树,然后再访问根结点,最后再中序遍历右子树。中序遍历运算访问二叉树各结点是以左、根、右的顺序进行访问的。例如:
按中序遍历此二叉树的结果为: a*b-c
proc inorder(bt:bitreprtr)
if (bt>null)[
inorder(bt^.lchild);
print(bt^);
niorder(bt^.rchild);]
end;
5.3.3 后序遍历
后序遍历运算:即先后序遍历左子树,然后再后序遍历右子树,最后访问根结点。后序遍历运算访问二叉树各结点是以左、右、根的顺序进行访问的。例如:
按后序遍历此二叉树的结果为: Welecome to use it!
proc postorder(bt:bitreprtr)
if (bt>null)[
postorder(bt^.lchild);
postorder(bt^.rchild);]
print(bt^);
end;
五、例:
1.用顺序存储方式建立一棵有31个结点的满二叉树,并对其进行先序遍历。
2.用链表存储方式建立一棵如图三、4所示的二叉树,并对其进行先序遍历。
3.给出一组数据:R={10.18,3,8,12,2,7,3},试编程序,先构造一棵二叉树,然后以中序遍历访问所得到的二叉树,并输出遍历结果。
4.给出八枚金币a,b,c,d,e,f,g,h,编程以称最少的次数,判定它们蹭是否有假币,如果有,请找出这枚假币,并判定这枚假币是重了还是轻了。
中山纪念中学三鑫双语学校信息学竞赛组编写 2004.7.15
㈡ 二叉树的存储结构是怎样的有哪些类型的存储结构对应的c语言描述是
线性表的链式存储结构:
typedef
int
elemtype;
typedef
struct
lnode
{
elemtype
data;
struct
lnode
*next;
}lnode,*linklist;
(被封装好的每个节点,都有一个数据域data和一个指针域*next用于指向下一个节点)
二叉树的二叉链表:
typedef
int
telemtype;
typedef
struct
bitnode
{
telemtype
data;
struct
bitnode
*lchild,*rchild;
}bitnode,*bitree;
(被封装好的每个节点,都有一个数据域data和两个指针域
*lchild,*rchild分别指向左右子树)
需要什么类型的数据作为数据域可更改,或者typedef
int
elemtype;和typedef
int
telemtype;中的int,比如改为char、float等或者自定义数据类型。
㈢ 一个二叉树按顺序方式存储在一个一维数组中,如图:
二叉树按照层序遍历,依次编号,按照编号的顺序,存储在连续存储单元的方式就是二叉树的顺序存储。
㈣ 二叉树的两种物理结构是什么
答:二叉树就物理结构来分可以分成:顺序存储结构和链式存储结构。
(1)顺序存储结构:
顺序存储结构,顾名思义就是二叉树的数据元素存放在一组连续的存储单元中。其主要有一下几个特点:
①逻辑上相邻的两个元素在物理位置上也是相邻的;
②操作删除和插入的时候,需要整体移动元素;
③需要预先分配空间,不能动态增长;
(2)链式存储结构:
链式存储结构中二叉树的每个结点至少包含三个域:数据域、左指针域和右指针域。其二叉树是通过指针实现,链式存储结构有以下几个特点:
①逻辑上相邻的两个元素在物理位置上不一定是相邻的;
②操作删除和插入的时候,不需要整体移动元素;只需要修改相应的指针即可;
③不需要预先分配空间;
④存储指针本身会消耗一定的存储的空间;
㈤ 二叉树_链式存储
二叉链:数据域(data)、左子结点域(lchild)、右子节点域(rchild)
定义:
求指定节点的左子节点地址:
求指定节点的右子节点地址:
二叉树的遍历:
定义: 按照某种顺序访问二叉树中的每个结点,使每个结点被访问一次且仅被访问一次;
用途: 它是树结构插入、删除、修改、查找和排序运算的前提,是二叉树一切运算的基础和核心;
遍历规则:
1、先序遍历(DLR): 头 -> 左 -> 右
2、中序遍历(LDR): 左 -> 头 -> 右
3、后序遍历(LRD): 左 -> 右 -> 头
先中后都是对于根结点而言。
二叉树遍历的递归实现:
访问方法:
先序遍历:
中序遍历:
后序遍历:
插一嘴:递归实现的思路清晰,易于理解,但是执行效率很低。非递归实现效率高些。
二叉树遍历的非递归实现:
先序遍历:
中序遍历:
后序遍历:好难-.-||略
利用“扩展先序遍历序列” 创建二叉树二叉链表:
1、若输入的字符是 '#',则建立空树;
2、否则建立根结点,接着递归建立左子树,然后递归建立右子树。