数据结构-图PPT
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
A
A
A
A
空二叉树
B
B
B
C
只有根结点
的二叉树
右子树为空
左子树为空
左、右子树 均非空
二叉树的五种不同形态
二叉树的抽象数据类型
基本操作:p121~p123 二叉树的建立和遍历
二叉树的性质
性质1 若二叉树的层Baidu Nhomakorabea从1开始, 则在二叉树的 第 i 层最多有 2i-1个结点。(i 1)
[证明用数学归纳法]
性质2 深度为k的二叉树最多有 2k-1个结点。 (k 1) [证明用求等比级数前n项和的公式Sn=a1(1-qn)/(1-q)]
中出栈溢出
while(!emptyStack(S)){ while(p){//结点p的所有左孩子入栈 push(S,p); p=p->lchild; }
//从循环中退出,说明栈顶结点无左孩子,可访问 pop(S,p); if(p){ printf("%c",p->data); p=p->rchild;//访问后,让p指向结点的右孩子 }
二叉树链表表示的示例
6.3 遍历二叉树 (Traversing Binary Tree) p128
所谓树的遍历,就是按某种次序访问树中的结点, 要求每个结点访问一次且仅访问一次。
遍历的结果:产生一个关于结点的线性序列。 设访问根结点记作 D
遍历根的左子树记作 L 遍历根的右子树记作 R 则可能的遍历次序有 先序 DLR DRL 逆先序 中序 LDR RDL 逆中序 后序 LRD RLD 逆后序
二叉树的存储结构
1. 顺序存储结构(数组表示)
6
完全二叉树的数组表示 一般二叉树的数组表示
完全二叉树:用数组依次从上而下,从左至右存储完全二叉树上的结点。 一般二叉树:将其每个结点与完全二叉树上的结点对照进行存储
由于一般二叉树必须仿照完 全二叉树那样存储,可能会 浪费很多存储空间,单支树 就是一个极端情况。
1. 树的定义 树是由n (n 0)个结点组成的有限集合。 如果n = 0,称为空树; 如果n > 0,则: ▪ 有一个特定的称之为根(root)的结点,它只有
后继,但没有前驱; ▪ 除根以外的其它结点划分为m (m 0)个互不
相交的有限集合T0, T1, …, Tm-1,每个集合本身又 是一棵树,并且称之为根的子树(subTree)。每棵 子树的根结点有且仅有一个直接前驱,但可以有 0个或多个后继。
A
B
C
D
E
F GH I
KL
M
堂兄弟:其双亲在同 一层的结点互为堂兄弟
有序树:如果将树中 结点的各子树看成从左 至右是有次序的,则该 树为有序树。否则为无 序树
基本术语
结点(node)——表示树中的元素,包括数 据项及若干指向其子树的分支
结点的度(degree)——结点拥有的子树数
树的度——一棵树中最大的结点度数
叶子(leaf)——度为0的结点
分支结点(非终端结点)--度不为0的结点
J 孩子(child)——结点子树的根称为该结点 的孩子
双亲(parents)——孩子结点的上层结点叫 该结点的~
兄弟(sibling)——同一双亲的孩子
祖先—是从根到该结点所经分支上的所有 结点
子孙—以某结点为根的子树中的任一结点 都称为该结点的~
树的定义和基本术语 二叉树 (Binary Tree) 二叉树的存储结构 遍历二叉树 (Binary Tree Traversal) 线索化二叉树 (Threaded Binary Tree) 树与森林 (Tree & Forest) 赫夫曼树 (Huffman Tree) 二叉树的计数
6.1 树的定义和基本术语
n2 = n0 - 1
n0 = n2 + 1
同理:
三次树: n0=1+n2+2n3
四次树: n0=1+n2+2n3+3n4
…
K次树: n0=1+n2+2n3+…+(k-1)nk
定义1 满二叉树(Full Binary Tree)
定义2 完全二叉树(Complete Binary Tree)
若设二叉树的深度为h,则共有h层。除第h层
先序:ABCDEFGHIJKL 中序:CBEFDGAJIKLH
遍历二叉树的非递归算法
先序遍历
从根结点开始,沿左子树向下
Status perOrder(BiTree T){//非递归实现先序访问树 SqStack S;
依次访问所经过的结点,同时所 BiTree p=T;
经结点的非空右孩子进栈
printf("树的先序访问结果为:);
限定访问先左后右,则只有三种遍历次序
先序遍历 (Preorder Traversal)
先序遍历二叉树算法的框架是 若二叉树为空,则空操作; 否则
访问根结点 (D); 先序遍历左子树 (L); 先序遍历右子树 (R)。
遍历结果(前缀表达式)
-+a*b-cd/ef
在前缀表示中(波兰式 中),自左到右依次扫 描:连续出现2个操作 数时,将其前面的运算 符退出,对该两操作数 进行这两个操作数前面 的运算符的运算,运算 的中间结果进栈,然后 再进行上述的操作。
中序遍历二叉树算法的框架是: 若二叉树为空,则空操作; 否则
中序遍历左子树 (L); 访问根结点 (D); 中序遍历右子树 (R)。
遍历结果(中缀表达式)
a+b*c-d-e/f
表达式语法树
中序遍历二叉树的递归算法
void InOrderTraverse(BiTree T){ if (T) { InOrderTraverse(T->lchild); printf("%c",T->data); InOrderTraverse(T->rchild); }
并回答下列问题:
1.哪个是根结点 2.哪些是叶子结点 3.哪个是结点G的双亲 4.哪些是结点G的祖先 5.哪些是结点G的孩子 6.哪些是结点E的子孙 7.哪些是结点E的兄弟?哪些是结点F的兄弟? 8.结点B和N的层次号分别是多少 9.树的深度是多少 10.以结点C为根的子树的深度是多少
1.A 2.D F J K L M N 3.C 4.A C 5.J K 6. I M N 7.D
当找到没有左孩子的结 点时,从栈顶退出该结 点并访问它, 此时,此结点的左子树 已访问完毕
在用上述方法遍历该结 点的右子树,如此重复 到栈空为止
Status inOrder(BiTree T){//非递归实现中序访问树 SqStack S; BiTree p=T; printf("树的中序访问结果为:"); initStack(S); push(S,NULL);//在栈底放一个NULL,以免循环
if(p->rchild) push(S,p->rchild);//将结点右孩子入栈 if(p->lchild)
p=p->lchild;//如果结点有左孩子则将指针移动到左孩子
A
else pop(S,p);//如果结点无左孩子,则将指针移动到右孩子
}
BF
return OK; }
CD G
E
中序遍历
从根结点开始,沿左子 树一直走,并将所经[结 点]进栈
结点的层次(level)——从根结点算起,根 为第一层,它的孩子为第二层……
深度(depth)——树中结点的最大层次数
森林(forest)——m(m0)棵互不相交的树 的集合
已知一棵树边的集合为{<I,M>,<I,N>,<E,I>,<B,E>,<B,D>,<A,B>,
<G,J>,<G,K>,<C,G>,<C,F>,<H,L>,<C,H>,<A,C>},请画出这棵树,
后序遍历二叉树的递归算法
void PostOrderTraverse(BiTree T){ if (T) { PostOrderTraverse(T->lchild); PostOrderTraverse(T->rchild); printf("%c",T->data); }
}
由二叉树的先序序列和中序序列可唯一地确定一 棵二叉树。例, 先序序列 { ABHFDECKG } 和中 序序列 { HBDFAEKCG }, 构练习造:二叉树过程如下:
Status CreateBiTree(BiTree &T) { char ch; scanf("%c",&ch);
GH 8.2 5 9. 5
10.3
树的抽象数据类型
树的基本操作:p119 树的建立和遍历——重点
6.2 二叉树 (Binary Tree)
二叉树的定义
一棵二叉树是结点的一个有限画出集具合有,3个该结集点的合二 或者为空,或者是由一个根结点加叉树上的两所棵有不分同别形称态: 为左子树和右子树的、互不相交的共5二种叉树组成。 特点:1)每个结点的度≤2;2)是有序树
#define MAX_TREE_SIZE 100
单支树
typedef TElemType SqBiTree[MAX_TREE_SIZE];
SqBiTree bt;
2.链式存储结构
typedef struct BiTNode{ //二叉链表的定义 TElemType data; Struct BiTNode *lchild,*rchild; }BiTNode, *BiTree;
先序遍历二叉树的递归算法
void PreOrderTraverse(BiTree T){ if (T){ printf("%c",T->data); PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); }
}
中序遍历 (Inorder Traversal)
当访问的结点没有左孩子时,此 initStack(S);
时,此结点的左子树已访问完毕, 从栈顶退出一个右孩子结点
push(S,NULL);//在栈底放一个NULL,以免循环中出栈溢出 while(!emptyStack(S)){
printf("%c",p->data);//访问当前结点
再用上述方法遍历该结点的右子 树,如此重复到栈空为止。
若i > 1, 则 i 的双亲为i /2 若2*i ≤ n, 则 i 的左孩子为2*i,否则无左孩子
若2*i+1 ≤ n, 则 i 的右孩子为2*i+1,否则无右 孩子 若 i 为偶数, 且i != n, 则其右兄弟为i+1
若 i 为奇数, 且i != 1, 则其左兄弟为i-1 i 所在层次为 log2 i +1
2k-1 - 1 < n 2k - 1 2k-1 n < 2k 取对数 k-1 log2n < k 因为k为整数,所以k = log2n +1 说明:常出现在选择题中
性质5 如果将一棵有n个结点的完全二1叉树的结 点按层序(自顶向下,同一层自左2 向右)连续3 编 号1, 2, …, n,然后按此结点编号将树中各结点顺 序地存放于一个一维数组中, 4并简称5 编号为6 i的结7 点为结点i (1 i n)。则有以8 下9 关10系1:1 12 若i == 1, 则 i 是二叉树的根,无双亲
性质3 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2, 则有
n0=n2+1
证明:若设度为1的结点有n1个,总结点个 数为n,总边数为e,则根据二叉树的定义,
n = n0 + n1 + n2 e = 2n2 + n1 = n - 1
因此,有 2n2 + n1 = n0 + n1 + n2 - 1
}
后序遍历 (Postorder Traversal)
后序遍历二叉树算法的框架是 若二叉树为空,则空操作; 否则
后序遍历左子树 (L); 后序遍历右子树 (R); 访问根结点 (D)。
遍历结果(后缀表达式)
abcd-*+ef/-
在逆波兰式中,自左到 右依次扫描:是操作数, 则依次进栈;遇到运算 符。则退出两个操作数, 对该两操作数进行该运 算符的运算,运算的中 间结果进栈;然后再继 续重复上述的操作。
外,其它各层(1h-1)的结点数都达到最大个数,
第h层从右向左连续缺若干结点,这就是完全二
叉树。 1
1
2
3
2
3
4
5
6
7
4
5
6
7
8 9 10 11 12 13 14 15 8 9 10 11 12
1
2
3
45
6
性质4 具有n个结点的完全二叉树的深度为
log2n +1 证明:设完全二叉树的深度为k,则有
} return OK; }
需用到栈,顺序栈的定义如下: typedef BiTNode* SElemType; typedef struct{
SElemType *base; SElemType *top; int stacksize; }SqStack;
先序建立二叉树的递归算法(p131,算法6.4)