数据结构学习考 复习课 (2)

59
数数数数数数数 数数数数数数数 数数数 数数数 (2) (2) 数数数数数数数数数数数数 数数 数数数数 数数 :、、 数数数数 数数 数数数数 数数 :、、

Upload: cana

Post on 16-Mar-2016

259 views

Category:

Documents


7 download

DESCRIPTION

数据结构学习考 复习课 (2). 主要内容: 第三部分:树、二叉树、森林. 第六章 树和二叉树. 考核内容及要求: 熟练掌握树的基本概念; 熟练掌握二叉树的概念、性质 熟练掌握二叉树的遍历方法,各种线索树、树与二叉树的转换、最优二叉树及 HUFFUMAN 编码; 掌握各种树操作特性、性质、实现方法. A. B. D. C. E. F. G. H. I. J. K. L. M. 1 树的基本概念、性质. 树: n 个结点的有限集; 在非空树中: 有且仅有一个根结点( Root ) ; - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 数据结构学习考 复习课 (2)

数据结构学习考数据结构学习考复习课复习课 (2)(2)主要内容:主要内容:第三部分:树、二叉树、森林第三部分:树、二叉树、森林

Page 2: 数据结构学习考 复习课 (2)

第六章 树和二叉树第六章 树和二叉树 考核内容及要求:考核内容及要求:

熟练掌握树的基本概念;熟练掌握树的基本概念; 熟练掌握二叉树的概念、性质熟练掌握二叉树的概念、性质 熟练掌握二叉树的遍历方法,各种线索树、树与熟练掌握二叉树的遍历方法,各种线索树、树与二叉树的转换、最优二叉树及二叉树的转换、最优二叉树及 HUFFUMANHUFFUMAN 编码;编码; 掌握各种树操作特性、性质、实现方法掌握各种树操作特性、性质、实现方法

Page 3: 数据结构学习考 复习课 (2)

1 树的基本概念、性质 树:树: nn 个结点的有限集;个结点的有限集;

在非空树中:在非空树中: 有且仅有一个根结点(有且仅有一个根结点( RooRoo

tt )) ;; 当当 n>1n>1 时,其余结点可以时,其余结点可以分为分为 mm 个个 (m>0)(m>0) 互不相交互不相交的有限集的有限集 TT11,T,T22,···,T,···,Tmm,, 其中其中

TiTi 为根的子树为根的子树

A

B C D

E F G H I J

K L M

Page 4: 数据结构学习考 复习课 (2)

树结构中的基本术语树结构中的基本术语 结点:一个数据元素及指向其子树的分支结点:一个数据元素及指向其子树的分支

结点的度:结点拥有的子树数结点的度:结点拥有的子树数 叶子结点:度为叶子结点:度为 0 0 的结点的结点 分支结点:度不为分支结点:度不为 00 的结点的结点

树的度:树内各结点的度的最大值树的度:树内各结点的度的最大值 孩子:结点的子树的根孩子:结点的子树的根 父亲父亲 (( 双亲双亲 )) :: 兄弟:同一父亲的孩子兄弟:同一父亲的孩子 祖先:从根到该结点所经分支上的所有结点祖先:从根到该结点所经分支上的所有结点 子孙:以某结点为根的子树中的任一结点子孙:以某结点为根的子树中的任一结点 层次:根为第一层,根的孩子为第二层层次:根为第一层,根的孩子为第二层 ······ 堂兄弟:双亲在同一层的结点互为堂兄弟堂兄弟:双亲在同一层的结点互为堂兄弟 深度:树中结点的最大层次深度:树中结点的最大层次 有序树:将树的结点的各个子树都看成是有序的,则有序树:将树的结点的各个子树都看成是有序的,则 无序树无序树 森林森林

A

B C D

E F G H I J

K L M

Page 5: 数据结构学习考 复习课 (2)

空二叉树空二叉树 仅有根结点仅有根结点的二叉树的二叉树

右子树为空的二叉树右子树为空的二叉树 左、右子树都左、右子树都不空的二叉树不空的二叉树

左子树为空的二叉树左子树为空的二叉树

二叉树的定义二叉树的定义 每个结点至多有两棵子树每个结点至多有两棵子树 (( 即度即度 <=2),<=2), 子树有左右之分。子树有左右之分。

二叉树的五种基本形态二叉树的五种基本形态

2 二叉树的概念、性质

Page 6: 数据结构学习考 复习课 (2)

二叉树的性质二叉树的性质 性质性质 1 1 在二叉树的第在二叉树的第 ii 层上至多有层上至多有 22i-1i-1 个结点(个结点( i≥1i≥1 ))

证明:归纳法证明:归纳法(1)(1) i=1i=1 时,命题显然成立,时,命题显然成立, 22i-1i-1=2=200=1=1

(2)(2)假设所有的假设所有的 1≤j<i1≤j<i 都成立,那么证明当都成立,那么证明当 j=ij=i 时命题也成立:时命题也成立:由假设知,第由假设知,第 i-1i-1 层上的结点个数为层上的结点个数为 22i-2i-2,, 而在二叉树中第而在二叉树中第 ii层上结点的个数最多是上一层结点数的层上结点的个数最多是上一层结点数的 22 倍,即为倍,即为2×22×2i-2i-2=2=2i-1i-1

Page 7: 数据结构学习考 复习课 (2)

性质性质 2 2 深度为深度为 kk 的二叉树至多有的二叉树至多有 22kk-1-1 个结点,(个结点,( k≥1k≥1 ))

证明:利用性质证明:利用性质 1 1 的结论的结论

1221

1

kk

i

i

Page 8: 数据结构学习考 复习课 (2)

性质性质 3 3 对任何一棵二叉树对任何一棵二叉树 TT ,如果其终端结点数为,如果其终端结点数为nn00,, 度为度为 22 的结点数为的结点数为 nn22,, 则则 nn00=n=n22+1+1

证明:设证明:设 nn11== 度为度为 11 的结点数,的结点数, nn 为结点总数,则为结点总数,则n=nn=n00+n+n11+n+n22 分析二叉树种的分叉数分析二叉树种的分叉数 BB ::n=B+1n=B+1B=nB=n11+2n+2n22所以有所以有 n=nn=n11+2n+2n22+1+1故:故: nn00=n=n22+1+1

Page 9: 数据结构学习考 复习课 (2)

满二叉树满二叉树:一棵深度为:一棵深度为 kk 且有且有 22kk-1-1 个结点的二叉树个结点的二叉树完全二叉树完全二叉树:深度为:深度为 kk 有有 nn 个结点的二叉树,当且仅个结点的二叉树,当且仅当其每一个结点都与深度为当其每一个结点都与深度为 kk 的满二叉树中编号从的满二叉树中编号从

11 至至 nn 的结点一一对应时,成为完全二叉树。的结点一一对应时,成为完全二叉树。

性质性质 4 4 具有具有 nn 个结点的完全二叉树的深度为个结点的完全二叉树的深度为log2n ++ 11

Page 10: 数据结构学习考 复习课 (2)

11

22 33

55

7766

11

22 33

44 55 66 77

1212111110109988

11

22 33

44 55 66 77

1212111110109988 14141313 1515

11

22 33

55 6644

满二叉树满二叉树 完全二叉树完全二叉树

非完全二叉树非完全二叉树

Page 11: 数据结构学习考 复习课 (2)

性质性质 5 5 如果对一棵有如果对一棵有 nn 个结点的完全二叉树(其深度个结点的完全二叉树(其深度为为 层, 每层从左到右),则对层, 每层从左到右),则对任一结点任一结点 i(1≤i≤n),i(1≤i≤n), 有:有:

(1) (1) 如果如果 ii == 11 ,则结点,则结点 ii 是二叉树的根,无双亲;若是二叉树的根,无双亲;若 i>1,i>1, 则其双亲则其双亲 pparent(i)arent(i) 是结点是结点(2) (2) 如果如果 2i>n,2i>n, 则结点则结点 ii 无左孩子无左孩子 (( 结点结点 ii 为叶子结点为叶子结点 )) ;否则其左孩;否则其左孩子子 LCHILD(i)LCHILD(i) 是结点是结点 2i.2i.(3) (3) 如果如果 2i+1>n,2i+1>n, 则结点则结点 ii 无右孩子;否则其右孩子无右孩子;否则其右孩子 RCHILD(i)RCHILD(i) 是结是结点点 2i+1.2i+1.

log2n ++ 11

i/2

i/2i/2

ii i+1i+1

2i+12i+1 2i+32i+32i2i 2i+22i+2

Page 12: 数据结构学习考 复习课 (2)

顺序存储结构顺序存储结构#define MAX_TREE_SIZE 100;#define MAX_TREE_SIZE 100;Typedef TElem Type SqBiTree[MAX_TREE_SIZE ]Typedef TElem Type SqBiTree[MAX_TREE_SIZE ] ;;SqBiTree bt;SqBiTree bt;将完全二叉树上编号为将完全二叉树上编号为 ii 的结点元素存储在一维数组的下标为的结点元素存储在一维数组的下标为

i-1i-1 的分量中。的分量中。

3 3 二叉树的存储结构二叉树的存储结构

Page 13: 数据结构学习考 复习课 (2)

链式存储结构链式存储结构———— 二叉链表二叉链表

DataData

LCHILD RCHILD

PARENTPARENT

lchild rchilddatalchild rchilddata parent

在含有在含有 nn 个结点的二叉链表中个结点的二叉链表中有有 n+1n+1 个空链域个空链域

DataData

LCHILD RCHILD

Page 14: 数据结构学习考 复习课 (2)

二叉链表的定义二叉链表的定义Typedef struct BiTNode{Typedef struct BiTNode{

TElemType data;TElemType data;

struct BiTNode *lchild, *rchild;struct BiTNode *lchild, *rchild;

}BiTNode, *BiTree;}BiTNode, *BiTree;

二叉树的基本操作:二叉树的基本操作:CreatBiTree(BiTree &T);//CreatBiTree(BiTree &T);// 按先序顺序构造一棵二叉树按先序顺序构造一棵二叉树PreOrderTraverse(BiTree T)PreOrderTraverse(BiTree T) ;; //// 先序遍历二叉树先序遍历二叉树InOrderTraverse(InOrderTraverse(BiTree TBiTree T)) ;; //// 中序遍历二叉树中序遍历二叉树PostOrderTraverse(PostOrderTraverse(BiTreeBiTree T)) ;; //// 后序遍历二叉树后序遍历二叉树LevelOrderTraverse(BiTree T)LevelOrderTraverse(BiTree T) ;; //// 层次遍历二叉树层次遍历二叉树

Page 15: 数据结构学习考 复习课 (2)

4 遍历二叉树和线索二叉树 遍历二叉树遍历二叉树

(( 11 )访问根结点)访问根结点(( 22 )先序遍历左子树)先序遍历左子树(( 33 )先序遍历右子树)先序遍历右子树

先序(根)遍历先序(根)遍历

(( 11 )中序遍历左子树)中序遍历左子树(( 22 )访问根结点)访问根结点(( 33 )中序遍历右子树)中序遍历右子树

中序(根)遍历中序(根)遍历

(( 11 )后序遍历左子树)后序遍历左子树(( 22 )后序遍历右子树)后序遍历右子树(( 33 )访问根结点)访问根结点

后序(根)遍历后序(根)遍历

Page 16: 数据结构学习考 复习课 (2)

例例 :: 表达式表达式 (a+b*(c-d)-e/f)(a+b*(c-d)-e/f) 的二叉树的二叉树-

+ /

a × fe

b

c

d

先序遍历二叉树:先序遍历二叉树:-+a*b-cd/ef-+a*b-cd/ef

中序遍历二叉树:中序遍历二叉树:a+b*c-d-e/fa+b*c-d-e/f

后序遍历二叉树:后序遍历二叉树:abcd-×abcd-× ++ ef/-ef/-

Page 17: 数据结构学习考 复习课 (2)

-+ /

a ×

--

++ //

aa bb

--

--

a

a b

/

b

++ //

bbaa

遍历二叉树的过程遍历二叉树的过程

Page 18: 数据结构学习考 复习课 (2)

线索二叉树线索二叉树 非线性结构的线性化操作非线性结构的线性化操作

增加两个指针:分别指向结点的前驱和后继增加两个指针:分别指向结点的前驱和后继利用二叉链表的利用二叉链表的 n+1n+1 个空链域个空链域

LTag=LTag=0 lchild0 lchild 指示左孩子指示左孩子1 lchild1 lchild 指示结点的前驱指示结点的前驱

RTag=RTag=0 rchild0 rchild 指示右孩子指示右孩子1 rchild1 rchild 指示结点的后继指示结点的后继

lchildlchild rchildrchildLTagLTag RTagRTagdatadata线索链表线索链表线索二叉树线索二叉树

Page 19: 数据结构学习考 复习课 (2)

00 11

thrtthrt

00 00--

00 00++ 00 00//

11 11aa 00 00**

11 11bb 00 00--

11 11-- 11 11--

00 11ee 00 11ff

bt

中序线索链表中序线索链表

Page 20: 数据结构学习考 复习课 (2)

在中序线索二叉树中找结点的后在中序线索二叉树中找结点的后继继 叶子结点的后继:右链域指示叶子结点的后继:右链域指示 非终端结点:其右子树的第一个结非终端结点:其右子树的第一个结点点

中序线索二叉树中找结点的前驱:中序线索二叉树中找结点的前驱: 左标志域为左标志域为 11 :左链域指示:左链域指示 左标志域为左标志域为 00 :左子树的最后一个:左子树的最后一个结点。结点。

-+ /

a × fe

b

c

d

NILNILNILNIL

中序线索二叉树中序线索二叉树

Page 21: 数据结构学习考 复习课 (2)

线索链表的存储结构线索链表的存储结构typedef enum PointerTag{Link,Thread};typedef enum PointerTag{Link,Thread};//Link==0://Link==0: 指针指针 ;Thread==1:;Thread==1: 线索线索typedef struct BiThrNode{typedef struct BiThrNode{

TElemType data;TElemType data;struct BiThrNOde *lchild,*rchild;//struct BiThrNOde *lchild,*rchild;// 左右孩子指针左右孩子指针PointerTag LTag,RTag;//PointerTag LTag,RTag;// 左右标志左右标志

}//BiThrNode, *BiThrTree;}//BiThrNode, *BiThrTree;

双向线索链表:双向线索链表:添加头结点:添加头结点: lchildlchild 域指向二叉树的根结点;域指向二叉树的根结点;rchildrchild 域指向中序遍历时访问的最后结点域指向中序遍历时访问的最后结点

Page 22: 数据结构学习考 复习课 (2)

5 树和森林 树的存储结构:树的存储结构:

双亲表示法:除根结点外的每双亲表示法:除根结点外的每个结点都只有唯一的双亲个结点都只有唯一的双亲RR

AA BB CC

DD EE FF

GG HH KK

RR

DD

CC

FF

HHGG

KK

AABB

EE

--11000000

33

1111

66

66

66

数组下标数组下标00

11

22

33

44

55

66

77

88

99

Page 23: 数据结构学习考 复习课 (2)

树的双亲表存储表示树的双亲表存储表示#define MAX_TREE_SIZE 100;#define MAX_TREE_SIZE 100;Typedef struct PTNode{Typedef struct PTNode{

TElemType data;TElemType data;int patent;int patent;

}//PTNode;}//PTNode;Typedef struct{Typedef struct{

PTNode nodes[MAX_TREE_SIZE];PTNode nodes[MAX_TREE_SIZE];int r,n;int r,n;

}//PTree;}//PTree;优点:优点: parent(T,x),Root(x)parent(T,x),Root(x) 操作容易实现操作容易实现确定:求结点的孩子时需要遍历整个结构确定:求结点的孩子时需要遍历整个结构

Page 24: 数据结构学习考 复习课 (2)

孩子表示法:孩子表示法:datadata child1child1 child2child2 child3child3 childdchildd······

datadata degreedegree child1child1 child2child2 childdchildd······

DD 为树的度,结点同为树的度,结点同构,空间浪费构,空间浪费结点不同构,空间不浪结点不同构,空间不浪费,操作不方便费,操作不方便

RRDDCC

FF

HHGG

KK

AABB

EE

00112233445566778899

3 5 ^

6 ^^

^

^

^^^

0 1 2 ^

7 8 9 ^

适用于涉及孩子的操作适用于涉及孩子的操作

Page 25: 数据结构学习考 复习课 (2)

树的孩子链表存储表示树的孩子链表存储表示Typedef struct CTNode{ //Typedef struct CTNode{ // 孩子结点孩子结点

int child;int child;struct CTNode *next;struct CTNode *next;}*childptr;}*childptr;

Typedef struct{Typedef struct{TElemType data;TElemType data;childptr firstchild; //childptr firstchild; // 孩子链表头指针孩子链表头指针}CTBox;}CTBox;

Typedef struct{Typedef struct{CTBox nodes[MAX_TREE_SIZE];CTBox nodes[MAX_TREE_SIZE];int n,r;int n,r; //// 结点数和根的位置;结点数和根的位置;}//CTree;}//CTree;

Page 26: 数据结构学习考 复习课 (2)

RRDDCC

FF

HHGG

KK

AABB

EE

44444400

-- 110022666666

3 5 ^

6 ^^

^

^

^^^

0 1 2 ^

7 8 9 ^

00112233445566778899

带双亲的孩子链表带双亲的孩子链表

孩子表示法和双亲表示法结合起来,即带双亲的孩子链表孩子表示法和双亲表示法结合起来,即带双亲的孩子链表

Page 27: 数据结构学习考 复习课 (2)

孩子兄弟表示法:以二叉链表表示孩子兄弟表示法:以二叉链表表示两个链域:两个链域: firstchildfirstchild 和和 nextsiblingnextsibling :第一个孩子结点和下一个:第一个孩子结点和下一个兄弟结点兄弟结点

Typedef struct CSNode{Typedef struct CSNode{

ElemType data;ElemType data;

Struct CSNode *firstchild,*nextsibling;Struct CSNode *firstchild,*nextsibling;

}CSNode,*CSTree;}CSNode,*CSTree;

RR ^̂

AA

DD BB

EE CC

FF

GG

HH

KK

Page 28: 数据结构学习考 复习课 (2)

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

BB CC EE

DD

AA

BB

CC

EEDD

AA

BB

CC

DD EE

^̂^̂^̂

任何一棵与树对应的二叉树,其右子树都为空任何一棵与树对应的二叉树,其右子树都为空

Page 29: 数据结构学习考 复习课 (2)

森林与二叉树的对应关系森林与二叉树的对应关系AA

BB CC DD

EE

FF

GG

IIHH

JJ

EE

FF

AA

BB

CC

DD

GG

II

HH

JJ

AA

BB

CC

DD

EE

FF GG

II

HH

JJ

树与二叉树对应

森林与二叉树

Page 30: 数据结构学习考 复习课 (2)

树和森林的遍历树和森林的遍历 树的遍历:树的遍历:

先根遍历先根遍历 后根遍历后根遍历

森林的遍历:森林的遍历: 先序遍历森林先序遍历森林 中序遍历森林:中序遍历森林:(( 11 )中序遍历森林中的第一颗树的根结点的子树森林;)中序遍历森林中的第一颗树的根结点的子树森林;(( 22 )访问第一颗树的根结点;)访问第一颗树的根结点;(( 33 )中序遍历剩余的树构成的森林。)中序遍历剩余的树构成的森林。

AA

BB CC DD

EE

FF

GG

IIHH

JJ

Page 31: 数据结构学习考 复习课 (2)

6 哈夫曼树及其应用 哈夫曼树:最优树,带权路径长度最短的树。哈夫曼树:最优树,带权路径长度最短的树。最优二叉树(哈夫曼树)最优二叉树(哈夫曼树) 路径:从树中一个结点到另一个结点之间的分支构成两个结点之间路径:从树中一个结点到另一个结点之间的分支构成两个结点之间的路径;的路径; 路径长度:路径上的分支数目;路径长度:路径上的分支数目; 树的路径长度:从树根到每一个结点的路径长度之和树的路径长度:从树根到每一个结点的路径长度之和 树的带权路径长度:树的带权路径长度:

其中:其中: wwkk 为为 kk 个结点的权值个结点的权值 最优二叉树最优二叉树 (( 哈夫曼树哈夫曼树 )) :带权路径长度:带权路径长度 WPLWPL 最小的二叉树最小的二叉树

n

kkklwWPL

1

Page 32: 数据结构学习考 复习课 (2)

构造哈夫曼树的过程构造哈夫曼树的过程

a b c d77 55 22 44

c d22 44

a b77 55 66

c d22 44

b55

1111a77

a

b

c d

77

55

22 44

1818

Page 33: 数据结构学习考 复习课 (2)

哈夫曼算法:哈夫曼算法:(1)(1) 根据给定的根据给定的 nn 个权值个权值 {w{w11,w,w22,···,w,···,wnn}} 构成构成 nn 棵二叉树的集合棵二叉树的集合 F={TF={T11,T,T

22,···,T,···,Tnn}} ,其中每棵二叉树,其中每棵二叉树 TTii 中只有一个带权为中只有一个带权为 wwii 的根结点,其左的根结点,其左右子树均空。右子树均空。(2)(2) 在在 FF 中选取两棵根结点的权值最小的树作为左右子树构造一棵新的中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左、右子树上根结点二叉树,且置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。的权值之和。(3)(3) 在在 FF 中删除这两棵树,同时将新得到的二叉树加入中删除这两棵树,同时将新得到的二叉树加入 FF 中。中。(4)(4)重复重复 (2)(3),(2)(3),直到直到 FF 只含一棵树为止。这颗树就是哈夫曼树。只含一棵树为止。这颗树就是哈夫曼树。

a b c d77 55 22 44

c d22 44

a b77 55 66

Page 34: 数据结构学习考 复习课 (2)

哈夫曼编码哈夫曼编码

A

B

C D

11

11

1100

00

00

编码 编码 A(0)A(0)

B(10)B(10)

C(110)C(110)

D(111)D(111)

哈夫曼树的特点:哈夫曼树的特点:没有度为没有度为 1 1 的结点,称为严格的二叉树的结点,称为严格的二叉树

Page 35: 数据结构学习考 复习课 (2)

哈夫曼树与哈夫曼编码的存储表示哈夫曼树与哈夫曼编码的存储表示Typedef struct{Typedef struct{

unsigned int weight;unsigned int weight;unsigned int parent,lchild,rchild;unsigned int parent,lchild,rchild;

}HTNode,*HuffmanTree;//}HTNode,*HuffmanTree;//动态分配数组存储哈夫曼树动态分配数组存储哈夫曼树Typedef char *HuffmannCode;//Typedef char *HuffmannCode;//动态分配哈夫曼编码表动态分配哈夫曼编码表

A

B

C D

11

11

1100

00

00 7 7 0 05 6 0 02 5 0 04 5 0 06 6 3 4

11 7 2 517 0 1 6

11

22

33

44

55

66

77

例如:例如:

Page 36: 数据结构学习考 复习课 (2)

构造哈夫曼树,求哈夫曼编码的算法构造哈夫曼树,求哈夫曼编码的算法void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int

n){//w 存放 n 个字符的权值,构造哈夫曼树 HT, 求 n 个字符的哈夫曼编码表 if (n<=1) return; m=2*n-1; //n 个字符的哈夫曼树有( 2*n-1 )个结点 HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); for (p=HT,i=1;i<=n;++i,++p,++w) *p={*w,0,0,0}; for (;i<=m;++i,++p) *p={0,0,0,0}; for (i=n+1;i<=m;++i){ // 构造哈夫曼树

select (HT,i-1,s1,s2);//选择 parent 为 0 且权值最小的两个结点: s1,s2 HT[s1].parnet=i; HT[s2].parent=i; HT[i].child=s1;HT[i].rchild=s2; HT[i].weight=HT[s1].weight+ HT[s1].weight; }

Page 37: 数据结构学习考 复习课 (2)

//// 从叶子到根逆向求每个字符的哈夫曼编码从叶子到根逆向求每个字符的哈夫曼编码HC=(HuffmanCode)malloc((n+1)*sizeof(char *));cd=(char*)malloc(n*sizeof(char));cd[n-1]=“\0” ;for(i=1;i<=n;++i){

start=n-1;for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) if (HT[f].lchild==c) cd[--start]=“0”; else cd[--start]=“1”;Hc[i]=(chat *)malloc((n-start)*sizeof(char));atrcpy(HC[i],&cd[start]);

}free(cd);}//HuffmanCoding

7 7 0 05 6 0 02 5 0 04 5 0 06 6 3 4

11 7 2 517 0 1 6

11

22

33

44

55

66

77

Page 38: 数据结构学习考 复习课 (2)

从根结点遍历哈夫曼树,求哈夫曼编码从根结点遍历哈夫曼树,求哈夫曼编码7 7 0 05 6 0 02 5 0 04 5 0 06 6 3 411 7 2 517 0 1 6

11

22

33

44

55

66

77

A

B

C D

11

11

1100

00

00

Page 39: 数据结构学习考 复习课 (2)

算法:算法:HC=(HuffmanCode)malloc((n+1)*sizeof(char*));HC=(HuffmanCode)malloc((n+1)*sizeof(char*));P=m; cdlen=0;P=m; cdlen=0;For(i=1;i<=m;++i) HT[i].weight=0;For(i=1;i<=m;++i) HT[i].weight=0;While(p){While(p){

if(HT[p].weight==0){if(HT[p].weight==0){ HT[p].weight=1;HT[p].weight=1; if (HT[p].lchild!=0) {p=HT[p].lchild; cd[cdlen++]=“0”;}if (HT[p].lchild!=0) {p=HT[p].lchild; cd[cdlen++]=“0”;} else if (HT[p].rchild==0){else if (HT[p].rchild==0){

HC[p]=(char *)malloc((cdlen+1)*sizeof(char));HC[p]=(char *)malloc((cdlen+1)*sizeof(char));cd[cdlen]=“\0”;atrcpy(HC[p],cd); }cd[cdlen]=“\0”;atrcpy(HC[p],cd); }

}else if (HT[p].weight==1{}else if (HT[p].weight==1{ HT[p].weight=2;HT[p].weight=2; if(HT[p].rchild!=0){p=HT[p].rchild; cd[cdlen++]=“1”;}if(HT[p].rchild!=0){p=HT[p].rchild; cd[cdlen++]=“1”;}}else {HT[p].weight=0;p=HT[p].parent;--cdlen;}}else {HT[p].weight=0;p=HT[p].parent;--cdlen;}

}//while}//while

Page 40: 数据结构学习考 复习课 (2)

6.2 6.2 一个度为一个度为 22 的树与一棵二叉树有何区别?的树与一棵二叉树有何区别? 答:二叉树的度小于等于答:二叉树的度小于等于 22 ,二叉树的子树有左,二叉树的子树有左右之分,而度为右之分,而度为 22 的树的子树不一定是有序的。的树的子树不一定是有序的。6.7 6.7 一棵含有一棵含有 nn 个结点的个结点的 kk 叉树,可能达到的最大深叉树,可能达到的最大深度和最小深度各是多少?度和最小深度各是多少? 答:最大答:最大 n, n, 最小最小 loglogkknn+1+1

典型例题典型例题

Page 41: 数据结构学习考 复习课 (2)

证明: 在含有证明: 在含有 nn 个结点的二叉链表中有个结点的二叉链表中有 n+1n+1个空链域个空链域 证明证明 : : 除根结点均有分支引出除根结点均有分支引出 ,, 故有故有 n-1n-1个分支个分支 , , 占用占用 n-1n-1 个子域个子域 ,n,n 个结点共有个结点共有 2n2n个子域个子域 .. 故空域共故空域共 2n-(n-1)=n+12n-(n-1)=n+1 个个 ..

Page 42: 数据结构学习考 复习课 (2)

6.10 6.10 对于那些所有非叶子结点均有非空左右子树对于那些所有非叶子结点均有非空左右子树的二叉树:的二叉树: 有有 nn 个叶子结点的树中共有多少个结点?个叶子结点的树中共有多少个结点?

性质性质 3 3 对任何一棵二叉树对任何一棵二叉树 TT ,如果其终端结点数为,如果其终端结点数为 nn00,,度为度为 22 的结点数为的结点数为 nn22,, 则则 nn00=n=n22+1+1

Page 43: 数据结构学习考 复习课 (2)

6.14 6.14 找出满足下列条件的二叉树找出满足下列条件的二叉树 11 )先序和中序遍历,得到的结点访问顺序)先序和中序遍历,得到的结点访问顺序一样。一样。 22 )后序和中序遍历,得到的结点访问顺序)后序和中序遍历,得到的结点访问顺序一样。一样。 33 )先序和后序遍历,得到的结点访问顺序)先序和后序遍历,得到的结点访问顺序一样。 一样。 答:答: 11 )无左子树 )无左子树 22 )无右子树 )无右子树 33 )仅)仅一个结点 一个结点

Page 44: 数据结构学习考 复习课 (2)

6.17 6.17 阅读下列算法,若有错,则改正。阅读下列算法,若有错,则改正。BiTree InSucc(BiTree q){BiTree InSucc(BiTree q){

//// 已知已知 qq 是指向中序线索二叉树上某个结点的指针,是指向中序线索二叉树上某个结点的指针,//// 本函数返回指向本函数返回指向 *q*q 的后继结点指针的后继结点指针r=q->rchild;r=q->rchild;if (!r->rtag)if (!r->rtag) while (!r->rtag) r=r->rchild;while (!r->rtag) r=r->rchild;return r;return r;

}//InSucc}//InSucc

Page 45: 数据结构学习考 复习课 (2)

6.19 6.19 分别画出和下列树对应的各个二叉树分别画出和下列树对应的各个二叉树 6.22 6.22 对于下列树分别求出以下遍历序列:对于下列树分别求出以下遍历序列:

(1) (1) 先根序列 先根序列 (2)(2) 后根序列后根序列AA AA

BB

CC

AA

BB CC

AA

BB CC DD

EE FF GG HH

II JJ KK

Page 46: 数据结构学习考 复习课 (2)

6.21 6.21 画出和下列二叉树对应的森林:画出和下列二叉树对应的森林:AA

BB

CC

AA

BB CC

AA

BB

CC

Page 47: 数据结构学习考 复习课 (2)

a

原则:森林的先序原则:森林的先序 // 中序遍历,即对应二叉树的先序中序遍历,即对应二叉树的先序 // 中中序序 遍历遍历先做二叉树:先做二叉树:cbefdg

6. 24 6. 24 画出和下列已知序列对应的森林画出和下列已知序列对应的森林 F:F:

森林的先序次序访问序列为:森林的先序次序访问序列为: ABCDEFGHIJKLABCDEFGHIJKL

森林的中序次序访问序列为:森林的中序次序访问序列为: CBEFDGAJIKLHCBEFDGAJIKLH

jiklh

a

jikl

b

efdgc

h

Page 48: 数据结构学习考 复习课 (2)

b h

c d i

a

ef g j kl

b h

c d i

a

g je

f

k

l

二叉树

先 ABCDEFGHIJKL

中 CBEFDGAJIKLH

Page 49: 数据结构学习考 复习课 (2)

b

h

c

d ig

je f

k l

a森林

6.23 6.23 画出和下列已知序列对应的树画出和下列已知序列对应的树 TT

树的先根次序访问序列为:树的先根次序访问序列为: GFKDAIEBCHJGFKDAIEBCHJ

树的后根次序访问序列为:树的后根次序访问序列为: DIAEKFCJHBGDIAEKFCJHBG

思路:树的先根为二叉树的先序思路:树的先根为二叉树的先序 树的后根为二叉树的中序树的后根为二叉树的中序 求出二叉树然后化为树求出二叉树然后化为树

Page 50: 数据结构学习考 复习课 (2)

6.42 6.42 编写递归算法,计算二叉树中叶子结点编写递归算法,计算二叉树中叶子结点的数目。的数目。Status PreOrderTraverse(BiTree T, int s) {Status PreOrderTraverse(BiTree T, int s) { //s//s 为叶子数目,初值为为叶子数目,初值为 0 0 if (T) {if (T) { if (!T->lchild) && (!T->rchild) s++;if (!T->lchild) && (!T->rchild) s++; PreOrderTraverse(T->lchild, s);PreOrderTraverse(T->lchild, s); PreOrderTraverse(T->rchild, s); }//ifPreOrderTraverse(T->rchild, s); }//if return OK;return OK; }//PreOrderTraverse}//PreOrderTraverse

Page 51: 数据结构学习考 复习课 (2)

6.47 6.47 编写按层次顺序(同一层自左至右)遍历二叉树编写按层次顺序(同一层自左至右)遍历二叉树的算法的算法Status LevelTraverse(BiTree T, Status LevelTraverse(BiTree T, status (*visit)(TElemType e) {status (*visit)(TElemType e) { InitQueue(Q);InitQueue(Q); if (T) EnQueue(Q,T);if (T) EnQueue(Q,T); while (!QueueEmpty(Q))while (!QueueEmpty(Q)) { DeQueue(Q,e);{ DeQueue(Q,e); if (!visit(e->data)) return ERROR;if (!visit(e->data)) return ERROR; if (e->lchild) EnQueue(Q,e->lchild);if (e->lchild) EnQueue(Q,e->lchild); if (e->rchild) EnQueue(Q,e->rchild);if (e->rchild) EnQueue(Q,e->rchild); }} return OK; }//LevelTraversereturn OK; }//LevelTraverse

Page 52: 数据结构学习考 复习课 (2)

习题习题 6.39 6.39 假设在二叉链表中增设两个域:双亲域指示双亲结点;假设在二叉链表中增设两个域:双亲域指示双亲结点;标志域标志域 (mark(mark 取值取值 0··2)0··2) 以区分在遍历过程中到达该结点时应该向以区分在遍历过程中到达该结点时应该向左、向右或访问该结点。试以此存储结构编写不用栈的后序遍历左、向右或访问该结点。试以此存储结构编写不用栈的后序遍历算法。算法。-

+ /

a ×

datadata lchildlchildparentparent rchildrchild markmark

分析:分析:每一个结点的每一个结点的 markmark初始化为初始化为00

mark=mark=

0 0 则访问左子树,同时则访问左子树,同时 markmark 变为变为11

1 1 则访问右子树,同时则访问右子树,同时 mark mark 变为变为22

2 2 访问根结点访问根结点

Page 53: 数据结构学习考 复习课 (2)

Status exercise_6.39(BiTree T,){Status exercise_6.39(BiTree T,){//// 后序遍历二叉树,后序遍历二叉树,二叉树的结点有五个域:二叉树的结点有五个域: data,parent,lchild,rchild,data,parent,lchild,rchild,mark;markmark;mark 初始值为初始值为 00

P=T;P=T;while (P){while (P){

swich (p->mark){swich (p->mark){case 0:case 0:

p->mark=1;p->mark=1;if (p->lchild) p=p->lchild; break;if (p->lchild) p=p->lchild; break;

case 1:case 1:p->mark=2;p->mark=2;if (p->rchild) p=p->rchild; break;if (p->rchild) p=p->rchild; break;

case 2:case 2:p->mark=0;visit(P);p->mark=0;visit(P);p=p->parent; break;p=p->parent; break;

default: ;default: ;}}

}}

Page 54: 数据结构学习考 复习课 (2)

6.62 6.62 对一个以孩子兄弟链表表示的树,计算对一个以孩子兄弟链表表示的树,计算它的深度它的深度RR ^̂

AA

DD BB

EE CC

FF

GG

HH

KK

Page 55: 数据结构学习考 复习课 (2)

队列中数据元素的类型定义队列中数据元素的类型定义Typedef struct QNode{Typedef struct QNode{

QElemtype data;QElemtype data;

int lay;int lay;

struct QNode *next;struct QNode *next;

}Qnode,*QueuePtr;}Qnode,*QueuePtr;

链队列的存储链队列的存储Typedef struct{Typedef struct{

QueuePtrQueuePtr front;;

QueuePtr QueuePtr rear;rear;

} LinkQueue;} LinkQueue;

Typedef struct CSNode{Typedef struct CSNode{

ElemType data;ElemType data;

Struct CSNode *firstchild,*nextsibling;Struct CSNode *firstchild,*nextsibling;

}CSNode,*CSTree;}CSNode,*CSTree;

Page 56: 数据结构学习考 复习课 (2)

Status D_S_6.62(CSTree tr;int layer){Status D_S_6.62(CSTree tr;int layer){ if tr=null return 0;if tr=null return 0; IniQueue(Q)IniQueue(Q) p=tr; InQueue(Q,p,1); layer=1;p=tr; InQueue(Q,p,1); layer=1; while (!EmptyQueue(Q)){while (!EmptyQueue(Q)){

OutQueue(Q,r);OutQueue(Q,r);if (!r->firstchild) if (!r->firstchild) {if r->lay>layer layer=r->lay;}{if r->lay>layer layer=r->lay;}if (r->firstchild) {if (r->firstchild) {k=r->lay+1;k=r->lay+1;p=r->firstchild;p=r->firstchild; while (p) {InQueue(Q,p,k); while (p) {InQueue(Q,p,k); p=p->nextsiblingp=p->nextsibling;};}}}

return layer;return layer;}}

Page 57: 数据结构学习考 复习课 (2)

6.26 6.26 假设用于通信的电文仅由假设用于通信的电文仅由 77 个字母组成,字个字母组成,字母在电文中出现的频率分别为母在电文中出现的频率分别为 0.07,0.19,0.02,0.06,0.07,0.19,0.02,0.06,0.32, 0.21,0.100.32, 0.21,0.10 ,试为这,试为这 77 个字母设计哈夫曼编码。个字母设计哈夫曼编码。使用使用 00~~ 77 的二进制表示形式是另一种编码方案。的二进制表示形式是另一种编码方案。比较两种方案的优缺点。比较两种方案的优缺点。 解题时注意哈夫曼树的最初存储结构和构造哈夫曼树的解题时注意哈夫曼树的最初存储结构和构造哈夫曼树的算法过程算法过程树的带权路径长度树的带权路径长度 WPL=SUM(WPL=SUM( 权值权值 ×× 路径长度路径长度 ))

•首先设首先设 77 个字符的权分别为个字符的权分别为 w={7, 19, 2, 6 ,32, 7w={7, 19, 2, 6 ,32, 7 , , 21, 21, 10}10}

n=7,n=7, 则则 m=13m=13 ,即在有,即在有 77 个叶子结点的哈夫曼树个叶子结点的哈夫曼树上有上有 1313 个结点个结点 然后构造一棵哈夫曼树:然后构造一棵哈夫曼树:

Page 58: 数据结构学习考 复习课 (2)

0.07,0.19,0.02,0.06,0.32, 0.21,0.100.07,0.19,0.02,0.06,0.32, 0.21,0.10 ,,77 19 2 6 32 21 10

7 19 32 21 10

2 6

8

19 32 21 10

7

2 6

8

15

19 32 21

10

7

2 6

8

15

25

32

10

7

2 6

8

15

25

19 21

40

19 21

40

32

10

7

2 6

8

15

25

60

Page 59: 数据结构学习考 复习课 (2)

19 21

40

32

10

7

2 6

8

15

25

60

100

最后得出字母的编码分别为:最后得出字母的编码分别为:(( 0.07,0.19,0.02,0.06,0.32, 0.21,0.100.07,0.19,0.02,0.06,0.32, 0.21,0.10 ))1110111011111111011110111111111111111010110110