ds ch5 en [兼容模式] - home.ustc.edu.cnhome.ustc.edu.cn/~huang83/ds/ds_ch5_en.pdf · §6.2.2...

22
2017/11/2 1 1 Data Structure Ch.6 Trees & Binary Trees Dr. He Emil Huang School of Computer Science and Technology Soochow University 苏州大学计算机科学与技术学院网络工程系 E-mail: [email protected] http://home.ustc.edu.cn/~huang83/ds.html 本章ppt与教材对应情况 本章涉及所有内容涵盖了教材以下章节 Chapter 10 (10.1 Binary Trees,二叉树) Chapter 11 (11.1 Orchards, Trees, and Binary Trees) Kruse的这部分结构并不是很合理(个人浅见),还是参考严 蔚敏老师书的结构吧,较之Kruse教材,本章我们补充内容 较多 2 3 A Brief Review of the Previous Contents Three key points in data structure researches logical structure of data storage structure of data operations on data structure (search, insert, delete, etc.) logical characteristics among data elements in linear list there is only one start node, one end node, and one precursor and successor relationship. one to one” logical structure hash list, etc. stack queue linked list sequential list different storage method Operation constraint linear list tree structure 树型结构 binary tree, tree, forest (Orchard), etc. there are branches among nodesthere exists a hierarchical relationship (结点间有分支,具有明显的层次关系) characteristics 树型结构特点 as for every node, there is only one immediate predecessor at mostbut there may be many immediate successors start node 开始结点—— root end nodes 终端结点—— leaves 叶子 other nodes 其余结点—— interior nodes 内部结点 application scenarios 树的应用 genealogy, administrative architecture, file directory in computer system Ch.6 Tree 5 §6.1 Definitions 树的概念 Def 树的定义:A tree is a finite set T consisting of n (n>=0) nodes, when T is NULL (n=0), which is called empty tree, otherwise it satisfies there is one and only one particular node called root, other nodes can be divided into m (m0) mutually disjoint subsets T 1 ,T 2 ,… T m , and every subset is also a tree, which is called subtree of the root. root branch node leaves §6.1 Definitions Recursive definition 递归定义 depict the inherent characteristics of the tree: a nonempty tree consists of several subtrees, a subtree consists of smaller subtrees. Several kinds of representation methods of tree 几种常 见的树型结构表示方法 non-intersect 不相交 containing 包含

Upload: others

Post on 19-Oct-2019

24 views

Category:

Documents


0 download

TRANSCRIPT

2017/11/2

1

1

Data StructureCh.6 Trees & Binary Trees

Dr. He Emil Huang

School of Computer Science and Technology

Soochow University

苏州大学计算机科学与技术学院网络工程系

E-mail: [email protected]

http://home.ustc.edu.cn/~huang83/ds.html

本章ppt与教材对应情况

本章涉及所有内容涵盖了教材以下章节

Chapter 10 (10.1 Binary Trees,二叉树)

Chapter 11 (11.1 Orchards, Trees, and Binary Trees)

Kruse的这部分结构并不是很合理(个人浅见),还是参考严蔚敏老师书的结构吧,较之Kruse教材,本章我们补充内容较多

2

3

A Brief Review of the Previous Contents

Three key points in data structure researches: logical structure of data storage structure of data operations on data structure (search, insert, delete, etc.)

logical characteristics among data elements in linear list: there is only one start node, one end node, and one

precursor and successor relationship. “one to one” logical structure

hash list, etc.

stack

queue

linked list

sequential listdifferentstorage method

Operation constraint

linear list

tree structure 树型结构 binary tree, tree, forest (Orchard), etc. there are branches among nodes,there exists a hierarchical

relationship (结点间有分支,具有明显的层次关系)

characteristics 树型结构特点 as for every node, there is only one immediate predecessor at

most,but there may be many immediate successors.

start node 开始结点—— root 根

end nodes 终端结点—— leaves 叶子

other nodes 其余结点—— interior nodes 内部结点

application scenarios 树的应用 genealogy, administrative architecture, file directory in

computer system

Ch.6 Tree

5

§6.1 Definitions 树的概念 Def 树的定义:A tree is a finite set T consisting of n (n>=0)

nodes, when T is NULL (n=0), which is called empty tree,otherwise it satisfies:

there is one and only one particular node called root,

other nodes can be divided into m (m≥0) mutually disjointsubsets T1, T2,… Tm, and every subset is also a tree, which iscalled subtree of the root.

root

branch node

leaves

§6.1 Definitions Recursive definition 递 归 定 义 depict the inherent

characteristics of the tree: a nonempty tree consists ofseveral subtrees, a subtree consists of smaller subtrees.

Several kinds of representation methods of tree 几种常见的树型结构表示方法

non-intersect 不相交

containing 包含

2017/11/2

2

7

§6.1 Definitions

① the degree of node:the amount of subtrees owned by one node (the degree of tree)

② Leaves 叶子:terminal nodes, whose degrees are 0③ branch nodes 分支结点:non-terminal nodes whose degrees

are larger than 0④ internal nodes 内部结点:branch nodes excluding root⑤ root 根结点: start node⑥ child、parent:the root of the subtree of one node is called

the child, this node is called the parent of the child.immediate predecessor (parent), immediate successor (child)

⑦ siblings(兄弟):nodes whose parents are the same with this node

Terms 树型结构中重要的术语

8

§6.1 Definitions

Terms 重要术语(续)⑧ Path(路径):Road (from top to bottom)

if there is a node sequence k1, k2, …,kj, which satisfiesthat ki is the parent of ki+1 (1≤i≤j-1), then this sequenceis a path or road from k1 to kj, whose length is j-1.

A

BC

D E F G

H I J

A B E JK1K2K3K4

the length of path from A to J is: j-1=4-1=3

9

§6.1 Definitions

Terms⑨ Ancestor and Descendant 祖先和子孙:if there exists one

path from k to ks, then k is the ancestor of ks and ks is thedescendant of k.

the ancestors of A are all nodes on the path from the rootto A.

the descendants of A are all nodes in the subtrees whoseroots are A.

⑩ Level (层数):counting from the root (1 or 0), the levels ofother nodes are the levels of their parents plus 1correspondingly.

Terms

⑪ Height (Depth) 树高:the largest level in all tree nodes.

⑫ Cousins 堂兄弟:whose parents are on the same level.

⑬ Ordered Tree、Unordered Tree (有序树、无序树):if the subtrees of every node are in order from left to right (non-interchangeable), then this tree is an ordered tree, otherwise it is an unordered tree.

different ordered trees, usually, we only discuss ordered tree

⑭ Forest:a set of m (m≥0) mutually disjoint trees

trees and forest are very similar:

tree, delete the root forest forest, add the root tree

§6.1 Definitions

11

A

B C

D

G

E F

H I J

example:§6.1 Definitions Logical Feature

Parent-Child Relationship (Nonlinear Relationship):every nodehas at most one immediate predecessor (parent), but severalimmediate successors (children).

Start Node:Root

End Node:Leaf

Ancestor-Descendant Relationship (纵向关系):which is the extension of parent-child relationship and defines the Vertical Relationship among tree nodes.

Transverse Relationship (横向关系):有序树定义了同一组兄弟间的从左到右的长幼关系,可将其延拓到结点间的横向次序:k1和k2是兄弟,k1在左,则k1的任一子孙在k2的任一子孙的左边.

}other nodes are internal nodes.

§6.2 Binary Tree (P430 in Kruse text book)a special tree structure, each node has no more than two subtrees, a general tree can be converted to a binary tree, which is used widely in computer science.

2017/11/2

3

13

§6.2.1 Definitions of Binary Tree

Def: A binary tree is a finite set consisting of n(n≥0) nodes, which is either empty, or it consists of a node called the root together with two mutually disjoint binary trees called the left subtree and the right subtree of the root. (Recursive Definition)

Some Possible States of Binary Tree (二叉树可能的形态)

a (b) (c) (d) (e)

a b cd e

A A A

14

§6.2.1 Definitions of Binary Tree

The difference between binary tree and ordered tree whosedegree is 2:when there is a node having only one child,apparently it is the eldest son (长子) when in ordered tree,but it needs to be distinguished between left and right whenin binary tree.

a normal ordered tree two different binary trees

the degree is 2

the degree is 2

Binary TreesBase Statues:

Two nodes: ?

Three nodes: ?

16

§6.2.2 Properties of Binary Tree

1. Property 1:There are at most 2i-1 nodes on the i-thlevel of the binary tree (i≥1, the root is in the first level)

Pf:Induction

① Induction Basis:i=1, 2i-1=1,第1层上只有根,故成立.

② Induction Hypothesis:设所有的j(1≤j<i)命题成立。即:第j层结点数 ≤ 2j-1

③ Induction Procedure:j=i时,第i-1层结点数≤2i-2(由归纳假设)

因为,每个结点至多有两个孩子.

所以,第i层上结点数≤2×2i-2=2i-1.

17

§6.2.2 Properties of Binary Tree

2. Property 2:There are at most 2h-1 nodes (h≥1) on the binary tree whose depth is h.

Pf:深度一定时,仅当每层上结点达到最大时,该树结点最多.利用性质1知,深度为h的二叉树至多有:

20+21+…+2h-1 = 2h-1

summation formula based on geometric progression:

18

§6.2.2 Properties of Binary Tree

3. Property 3.In an arbitrary binary tree T, let n0 bethe amount of leaves and n2 be the amount of nodeswhose degrees are 2. then n0=n2+1 holds.

Pf: 设n1为度为1的结点总数,则结点总数n等于0度,1度和2度结点数之和

n = n0+n1+n2 // 二叉树 (6.1)

另一方面,除根外,其余结点均是其双亲的孩子,树中:

孩子结点总数 = n1+2n2 n-1 = n1+2n2

n = n1+2n2+1 (6.2)

由6.1和6.2:

n0=n2+1

A

BC

D E F

2017/11/2

4

19

§6.2.2 Properties of Binary Tree4. Full Binary Tree (满二叉树):If the amount of nodes

in a binary tree whose depth is h is 2h-1, then this treeis a full binary tree.

5. Complete Binary Tree (完全二叉树):If the nodeswhose degrees are less than 2 are all on the highest 2levels, and nodes on the highest level are all on theleft, then this tree is a complete binary tree.

if a node does not have left child, then it is a leaf nodedefinitely (it is impossible to have right child)

Full Binary Tree is Complete Binary Tree, but the converse is not always true.

20

Question?except leaves, every node has left and right subtrees

Is such a tree a full binary tree?

Answernot sure

leaves can only appear in the highest level and the degrees of nodes which are not leaves must be 2

A

BC

D E F G

H I J K

21

A

BC

D E F G

H I J完全二叉树示例

22

A

B C

GFE

H I

D

KJ ML

(a) 完全二叉树示例

(b) 非完全二叉树示例

ON

A

B C

GFE

H I

D

KJ L NM

23

§6.2.2 Properties of Binary Tree

6. Property 4.If a Complete Binary Tree contains nnodes, then its height is lgn +1 or lg(n+1) .

Proof:

∵ 树高为h,则前h-1层是高为h-1的满二叉树,结点总数 = 2h-1-1.

∴ 2h-1-1 < n ≤ 2h-1 (2h-1 < n+1 ≤ 2h) // 第h层上至少有一个结点

2h-1 ≤ n < 2h //整数

h-1 ≤ lgn < h (h-1 < lg(n+1) ≤ h)

∵ h-1和h是相邻的整数

∴ h-1 = lgn (h = lg(n+1) )

24

§6.2.3 Storage Structure of Binary Tree1. Sequence Storage StructureHow to linearize nodes to make that mutual locations in linearsequence can reflect the logical relationship among nodes?if we number all n nodes for complete binary tree from top tobottom, from left to right in every level, we can obtain a linearsequence which is enough to reflect the whole structure of binarytree.

∵ 完全二叉树除最下层外,各层都充满了结点,每层结点数恰为上层的2倍.

∴ 从一结点编号可推出其双亲,左右孩子,兄弟结点和编号.

2017/11/2

5

25

§6.2.3 Storage Structure of Binary Tree

Property 5. suppose that ki (1≤i≤ n) represents the i-thnode in the complete binary tree, then:

1)若i=1,则结点ki为根,无双亲;若i>1,则ki的双亲是k i/2

2)若2i≤n,则ki的左孩子为k2i;否则ki无左孩子,即它必为叶子。

//因此,完全二叉树中编号i> n/2 的结点必为叶子;

3)若2i+1≤n,则ki的右孩子为k2i+1 ,否则ki无右孩子;

4)若i为奇数且大于1,则ki的左兄弟为ki-1,否则ki无左兄弟;

5)若i为偶数且小于n,则ki的右兄弟为ki+1,否则ki无右兄弟。

证明从略。

∵in the relationship mentioned above, number is enough to reflect the logical relationship between the nodes

∴we store n nodes in vector bt[0..n], in which:

bt[0] —— do not use, or store n

bt[1..n] —— 存储编号为1~n的结点

26

§6.2.3 Storage Structure of Binary Tree

2i+32i+22i+12i

i+1i

/ 2i

Disadvantage:

As for a general binary tree, it should be stored according to the number in complete binary tree, which is space-consuming. The worst case is right single tree, and k nodes need 2k-1 node spaces.

Conclusion

This kind of structure is only suited to store complete binary tree, but it is inconvenient for

inserting and deleting. 27

§6.2.3 Storage Structure of Binary Tree

28

§6.2.3 Storage Structure of Binary Tree

2. Linked Storage Structure 链式存储结构 Structure of Node 结点结构

Definition of Nodetypedef struct node {

DataType data;

struct node *lchild, *rchild;

} BinTNode; // 结点类型

typedef BinTNode *BinTree; //二叉树类型

严蔚敏老师教材解释为三叉链表

In binary tree, all nodes whose types are BinTNode along with a

BinTree-type head pointer root, which points to the root, constitute

the linked storage structure of binary tree, which is called Binary

Chained List (二叉链表, linked binary tree P439 in text book).

Apparently, a binary chained list can be uniquely determined by

root pointer.

Example

Characteristic

Empty Tree root = NULL

Leaf left and right pointers are NULL

The Amount of Null Pointers :

n nodes, 2n pointer fields, but only n-1 nodes are the children ofother nodes, so the number of null pointers are n+1 2n-(n-1)

(a) binary tree

(b) binary linked list

30

§6.3 Traversal of Binary Trees (critical!)

1. Concept (P432 in text book)

Definition: along with a certain searching route, traversingoperation visits every node in the tree once and only oncesuccessively.

Importance: traversing operation is the foundation of otheroperations, many operations on tree are all rely on traversingoperation, but the operations are different when visiting nodes.

How to Traverse?

It is easy to traverse linear structure:from start node,visit thesuccessor of current node successively,to end node. There is onlyone traversal route(for example, single linked list, from head pointer)

But each node may have two successors in binary tree, so thetraversal route is not unique, so the same rule of traversal which issuitable for every node need to be found.

2017/11/2

6

§6.3 Traversal of Binary Trees∵in the recursive definition of binary tree, a nonempty tree is

composed of:D、L、R

1 DLR LDR LRD3

DRL RDL RLD

.从左到右: , ,二者对称,只讨论前 种

2.从右到左: , ,

∴at every node, perform three operations according to a certainorder:

Visit the Root Node (D)

Traversal of the Left Subtree of Current Node (L)

Traversal of the Right Subtree of Current Node (R)

apparently, there are six execution orders:

root

left subtree right subtree

which are symmetrical (对称),only discuss the first three 32

§6.3 Traversal of Binary Trees

Traversal Rules (From Left to Right)

the difference among DLR, LDR, LRD is that orders ofvisiting the root are different (差别为访问根的先后次序不同)

① preorder(先序、先根)traversal:DLR

② inorder(中序、根)traversal:LDR

③ postorder(后序、根)traversal:LRD

root

left subtree right subtree

Traversal of Binary Trees

With preorder traversal we first visit a node, then traverse its left subtree, and then traverse its right subtree.

With inorder traversal we first traverse the left subtree, then visit the node, and then traverse its right subtree.

With postorder traversal we first traverse the left subtree, then traverse the right subtree, and finally visit the node.

§6.3 Traversal of Binary Trees

34

2. Traversal Algorithm

take 中根(inorder) traversal for example, the definition of traversing binary tree is:if 二叉树非空 then {

(1) 遍历左子树 // 即遍历二叉树

(2) 访问根 // 将(1)(2)和(2)(3)对调后为先序和后序遍历

(3) 遍历右子树 //即遍历二叉树

} // 否则为空操作 (递归结束条件)

void Inorder(BinTree T) { // T为二叉树的头指针,等价于BinTNode*Tif (T) { // T非空,T为空时为空操作

Inorder(T->lchild); // 递归遍历左子树

printf(“%c”, T->data);// 访问根结点,具体问题,此

// 操作不同

Inorder(T->rchild); // 递归遍历右子树}

} Time:O(n)

A

B C

D E F

G H I

J Preorder Sequence:ABDGJEHCFIInorder Sequence:DJGBHEAFICPostorder Sequence:JGDHEBIFCA

36

A

B C

D E F

G H I

J

D J G B H E A F I C

投影法求中序遍历序列要点:图要画准

2017/11/2

7

Preorder Sequence:ABDHKECFIGJInorder Sequence:HKDBEAIFCGJPostorder Sequence:KHDEBIFJGCA

A

B C

D E F

H I

G

J

K

Test:

A

B

C

D

E

Fpreorder:

inorder:

postorder:

ABCDEF

BCADFE

CBFEDA

D

E

39

§6.3 Traversal of Binary Trees

D EF

D E F

AB C

BA C

D EFB CA

前序序列:

中序序列: 线性序列:

后序序列:

envelope line (包络线) is the recursive traversal route

Down:indicate recursive call is deeper (更深一层)

Up: indicate recursive call isover, return previous level

1个开始结点,1个终端结点,其余结点均有一个直接前驱和一个直接后继,为区别3种次序在前面冠以

前序前驱

中序 +后继

后序

▲叶子的相对次序相同

每个结点经过3次,第1次经过时访问所得结点序列为前序,第2次经过时访问所得结点序列为中序,第3次经过时访问所得结点序列为后序。

虚结点

3. traversal of sequence

40

4. General Traversal Algorithm因为访问结点的操作依赖于具体问题,故可将它作为一个函数指针参数放于遍历算法的参数表中,调用时,使其指向具体的访问结点的应用函数

void Inorder (BinTree T, void (*Visit)(DataType x) ) {

if (T) {

Inorder(T->lchild, Visit);

Visit(T->data); // (*Visit)(T->data)

Inorder(T->rchild, Visit);

}

}

其中Visit是一函数指针,它指向形如void f(DataType x)的函数,故可将访问结点的操作写在函数f中,通过调用语句

Inorder(root, f);

将f的地址传给Visit。

41

§6.3 Traversal of Binary Trees4. General Traversal Algorithm (cont.)

例如,可将打印操作定义为函数

void print(DataType x) {

printf(“%c”, x);

}

调用Inorder(root, print),即可完成前述算法。

▲ 函数名:函数代码的起址

42

二叉树的中序通用遍历算法

Template <class T>void BinaryTree<T>::InOrder(BinTreeNode<T> *subTree,

void (* visit)(BinTreeNode<T> *p)){

//递归函数:此算法按照中序次序遍历以subTree为根的子树if(subTree!=NULL) //等于NULL是递归终止条件{

InOrder(subTree->leftChild, visit);//中序遍历根的左子树visit(subTree);//访问根结点Inorder(subTree->rightChild, visit);//中序遍历根的右子树

} //endif};

2017/11/2

8

§6.3 Traversal of Binary Trees Build Binary Chained List 建立二叉链表the above algorithm assume that the binary chained list has been established 上述算法假定二叉链表已经建立

there are many binary chained list methods corresponding to establishing binary tree

Preorder Traversal Construction Method input preorder sequence, add virtual nodes (utilize space character“ ”when

input) to indicate the position of

null pointer, for example as for

aforementioned binary tree, the input is:

ABDФФФCEФФFФФ44

§6.3 Traversal of Binary Treesvoid CreateBinTree(BinTree *T) { // 注意T为指针的指针

char ch;if ((ch = getchar( )) == ‘\n’) return; // 回车结束输入

if (ch == ‘ ’) // 读入空格

*T = NULL; // 将相应的指针置空

else { // 读入的是结点数据

*T = (BinTNode*) malloc(sizeof(BinTNode)); (*T)->data = ch; // 生成新结点,相当于访问根节点

CreateBinTree(&(*T)->lchild); // 建立左子树

CreateBinTree(&(*T)->rchild); // 建立右子树}

}

建树时调用 CreateBinTree(&root), 将root(BinTree类型)的地址复制给T,故修改*T就相当于修改了实参root本身。

Time:O(n)

45

应用前序遍历建立二叉树的算法

Template <class T>void BinaryTree<T>::CreateBinTree(ifstream& in, BinTreeNode<T> *& subTree){

//私有函数:以递归方式建立二叉树T item;if( !in.eof( ) ) { //未读完,读入并建树

in>>item; //读入根节点的值if(item!=RefValue){

subTree=new BinTreeNode<T> (item);//建立根节点if(subTree==NULL){cerr<<“存储分配错误!”<<endl; exit(1);}CreatBinTree(in, subTree->leftChild);//递归建立左子树CreatBinTree(in, subTree->rightChild);//递归建立右子树

}else subTree=NULL; //封闭指向空子树的指针

}}

Textbook中相应内容

P430~P444

Binary Trees Expression Trees (表达式树, P435)

表达式(数学表达式或逻辑表达式)树是由运算符和操作数构成

树的前序、中序、后序三种遍历方式与表达式描述之间的联系

Binary Trees Expression Trees

2017/11/2

9

对树的遍历操作 表达式的形式

前序序列 前缀表达式中序序列 中缀表达式

后序序列 后缀表达式

Linked Binary Tree Specifications(链式二叉树结构说明)

Binary Tree Class (P437)

template <class Entry>class Binary_tree {

public:// Add methods here.protected:// Add auxiliary(备用) function prototypes here.Binary_node <Entry> *root;

};

Linked Binary Tree Specifications(链式二叉树结构说明)

Binary node class: (二叉树结点类, P438)

template <class Entry>struct Binary_node { //带构造函数的结构体定义

// data members:Entry data;Binary_node<Entry> *left;Binary_node<Entry> *right;// constructors:Binary_node( );Binary_node(const Entry &x);

};

Linked Binary Tree Specifications(链式二叉树结构说明)

Constructor: (初始化)

template <class Entry>

Binary_tree<Entry> :: Binary_tree( )

/* Post: An empty binary tree has been created. */

{

root = NULL;

}

Linked Binary Tree Specifications(链式二叉树结构说明)

Empty: (判空)

template <class Entry>

bool Binary_tree<Entry> :: empty( ) const

/* Post: A result of true is returned if the binary tree is empty. Otherwise, false is returned. */

{

return root == NULL;

}

Linked Binary Tree Specifications(链式二叉树结构说明)

Inorder traversal: (中序遍历)

template <class Entry>

void Binary_tree<Entry> :: inorder (void (*visit)(Entry &))

/* Post: The tree has been traversed in inorder sequence.

Uses: The function recursive_inorder */

{recursive_inorder(root, visit); //中序遍历函数

}

2017/11/2

10

Linked Binary Tree Specifications(链式二叉树结构说明)

Most Binary tree methods described by recursive processes can be implemented by calling an auxiliary recursive function that applies to subtrees调用一个应用于子树的辅助递归函数实现.

Linked Binary Tree Specifications(链式二叉树结构说明,P440)

template <class Entry>void Binary_tree<Entry> :: recursive_inorder(Binary_node<Entry> *sub_root, void (*visit)(Entry &)){

if (sub_root != NULL) {

recursive_inorder(sub_root->left, visit);(*visit)(sub_root->data);recursive_inorder(sub_root->right, visit);

}}

Linked Binary Tree Specifications(链式二叉树结构说明)

template <class Entry>class Binary_tree {public:

Binary_tree( );bool empty( ) const;void preorder(void (*visit)(Entry &));void inorder(void (*visit)(Entry &));void postorder(void (*visit)(Entry &));int size( ) const;void clear( );int height( ) const;void insert(const Entry &);

Linked Binary Tree Specifications(链式二叉树结构说明)

Binary_tree (const Binary tree<Entry> &original);

Binary_tree & operator = (const Binary_tree<Entry> &original);

~Binary_tree( );

…..

protected:

// Add auxiliary function prototypes here.

Binary_node<Entry> *root;

};

template <class Entry>

int Binary_tree<Entry> :: recursive_size (Binary_node<Entry>

*sub_root) const {

/* Post: The number of entries in the subtree rooted at sub_root is returned. */

if (sub_root == NULL) return 0; //递归结束,空树结点数为0

return (1+recursive_size (sub_root->left)+ recursive_size(sub_root->right));

}

写出二叉树结点计数的算法 统计二叉树高度的算法

template <class Entry>

int Binary_tree<Entry> :: recursive_height(Binary_node<Entry> *sub_root) const {

/* Post: The height of the subtree rooted at sub_root is returned. */

if (sub_root == NULL) return 0;

int i = recursive_height(sub_root->left);

int j = recursive_height(sub_root->right);

if (i > j) return i + l;

else return j+1;

}

2017/11/2

11

拷贝构造函数

template <class Entry>

Binary_tree<Entry>::Binary_tree(const Binary_tree<Entry>& s){

//public, copy constructor

root = recursive_copy (s.root);

}

Binary_node<Entry> * Binary_tree<Entry> :: recursive_copy (

Binary_node<Entry> *sub_root) {

/* Post: The subtree rooted at sub_root is copied, and a pointer to the root of the new copy is returned. */

if (sub_root == NULL) return NULL;

Binary_node<Entry> *temp = new Binary_node<Entry>(sub_root->data);

temp->left = recursive_copy(sub_root->left); //复制左子树

temp->right = recursive_copy(sub_root->right); //复制右子树

return temp; //返回根指针

}

template <class Entry>

void Binary_tree<Entry> :: clear( ){

recursive_clear(root);

}

template <class Entry>

void Binary_tree<Entry>::recursive_clear(Binary_node<Entry> * &sub_root){

if (sub_root != NULL)

{

recursive_clear(sub_root->left);

recursive_clear(sub_root->right);

delete sub_root;

sub_root=NULL;

}

}

二叉树清空

叶子结点删除template <class Entry>

void Binary_tree<Entry>:: recursive_deleteleaf

(Binary_node<Entry>* &sub_root){

if(sub_root==NULL)

return;

if (sub_root->left==NULL && sub_root->right==NULL)

{delete sub_root; sub_root=NULL; return;}

recursive_deleteleaf(sub_root->left);

recursive_deleteleaf(sub_root->right);

}

template <class Entry>

void Binary_tree<Entry>:: deleteleaf( ){

recursive_deleteleaf(root);

}

Non-recursive algorithm design for the issue of binary tree

traverse

二叉树遍历的非递归算法设计

Non_recursive Inorder traversal 1、初始化空栈S,p=root;

2、当p不为空时,执行循环:

p入S栈

p=p->left;

3、当S栈非空时,

出栈p

访问p所指结点,

p=p->right,

如果p为空,继续出栈(循环至3);

如果p不为空,循环至2

4、否则结束

Non_recursive inorder traversal

1. 设置一个空栈S

2. 设置活动指针p,初值p=root

3. 当栈S不空时或p不空时,执行循环{① 当p不为NULL时重复循环:p入栈,p=p->left;

② 当S不空时,出栈栈顶p,访问p->data

③ p=p->right

4. }

2017/11/2

12

Level traversal

1. 设置一个队列

2. root指针入队

3. 在队列非空时{① 出队p

② 访问p->data

③ 将p的非空左右孩子入队

4. }

68

§6.4 Threaded Binary Tree

A∧

C∧

B∧

Question:1. 每个结点都包含两个指针域,但是这些指针域是否得以充分

利用?2. n个结点的二叉链表存在多少个空指针域?

写出此棵包含三个结点的二叉树的二叉链表

A

B C

D E F

G H I

J Preorder Sequence:ABDGJEHCFIInorder Sequence:DJGBHEAFICPostorder Sequence:JGDHEBIFCA 70

§6.4 Threaded Binary Tree

A∧

C∧

B∧

A

C

B

NIL

1. Basic Concepts

在一基本数据结构上常常需要扩充,增加辅助信息,其目的是:

①Develop New Operations②Accelerate Existing Operations

Thread —— 利用空指针域(n+1个)存放指向结点在某种遍历次序下的前驱和后继指针

Threaded Linked List —— 加上线索的二叉链表

Threaded Binary Tree —— 相应的二叉树称为线索二叉树

Objective:加速遍历操作

加速查找任一结点在某种遍历次序下的前驱和后继操作

如何区别结点的指针域

Child Pointer:指向孩子?

Thread Pointer:指向某种遍历次序下的前驱和后继的线索?

§6.4 Threaded Binary Tree

72

§6.4 Threaded Binary Tree1. Basic Concepts Node Structure

Thread Tag

中序线索树和中序线索链表

0 : lchildltag =

1: lchild

0 : rchildrtag =

1: rchild

为左指针,指向孩子左标志

为左线索,指向前驱

为右指针,指向孩子右标志

为右线索,指向后继

中序序列:CBDAFHGIE

2017/11/2

13

73

§6.4 Threaded Binary Tree

NULL

NULL

开始结点,左线索为中序序列 中序为对称序

终端结点,右线索为

1. Basic Concepts 中序线索树中必有两个指针域为空

前序线索树中,有几个指针域为空?

前序序列的开始结点为根,故当它的左子树非空时,其指针域指向左指子树,此时前序序列开始结点左指针非空。

但是,前序序列的终端结点的右指针必为空。

仅当只有1个根结点或根的左子树为空时有两个空指针。

开始结点为最左下的结点中序序列

终端结点为最右下的结点

74

§6.4 Threaded Binary Tree1. Basic Concepts

后序线索树中,开始结点的左指针必为空,仅当只有1个根时或根的右子树为空时有两个空指针。

与前序线索树对称

带头结点的线索链表

书上6.11图(b). 令空指针也指向此哨兵

指向终端结点(一般)线索

指向开始结点(更好,有利于遍历操作)

75

线索树中,如何判定结点是否为叶子?

ltag = rtag = 1 (适用于三种线索树) 有时线索树只有左线索或右线索之一

2. 线索化将二叉树变为线索树的过程

按某种次序遍历,在遍历过程中用线索取代空指针。

typedef enum {Link, Thread} PointerTag; // 0为Link,1为Threadtypedef struct node {

DataType data;PointerTag ltag, rtag;struct node *lchild, *rchild;

} BinThrNode, *BinThrTree;

设p和pre分别指向遍历过程中当前访问结点和其前驱,即*pre和*p是前驱和后继的关系,其中pre为全局量,在遍历过程中建立线索。

以中序为例,pre初始为NULL,因为中序前驱对开始结点是NULL。

76

void InorderThreading(BinThrTree p) { // pre为全局量,初值为NULLif (p) {

InorderThreading( p->lchild ); // 左子树线索化

p->ltag = (p->lchild) ? Link : Thread; // 左指针非空,置为

// Link,否则为线索。

p->rtag = (p->rchild) ? Link : Thread;if (pre) { // 若*pre存在

if (pre->rtag == Thread) // 当前结点*p的前驱右标志为线索

pre->rchild = p; // 令*pre的右线索指向中序后继*p if (p->ltag == Thread) // 当前结点的左线索已建立

p->lchild = pre; //令当前节点的左线索指向中序前驱}pre = p; //使*pre为*p的前驱,循环不变量

InorderThreading( p->rchild ); // 右子树线索化}

} Time:和遍历相同O(n). 后序(前序)线索化类似于此。

访问根结点

中序线索二叉树的类定义

template <class T>struct ThreadNode//线索二叉树的结点类{

int ltag, rtag;//线索标志ThreadNode<T> *leftChild, *rightChild;//线索或子女指针T data;//结点中所包含的数据ThreadNode(const T item):data(item),leftChild(NULL), rightChild(NULL),ltag(0), rtag(0){}//构造函数

};

利用中序遍历对二叉树进行中序线索化template <class T>void ThreadTree<T>::createInThread(){

ThreadNode<T> *pre=NULL;//前驱结点指针if(root!=NULL)//非空二叉树,线索化{

creatInThread(root,pre);//中序遍历线索化二叉树pre->rightChild=NULL; pre->rtag=1;//处理中序最后一个结点

}

};

2017/11/2

14

template <class T>void ThreadTree<T>::createInThread(ThreadNode<T> *current,

ThreadNode<T> *& pre){//通过中序遍历,对二叉树进行线索化

if(current==NULL) return;createInThread(current->leftChild, pre);//递归,左子树线索化if(current->leftChild==NULL)//建立当前结点的前驱线索{current->leftChild=pre; current->ltag=1;}if(pre!=NULL&&pre->rightChild==NULL)//建立前驱结点的后继线索{pre->rightChild=current; pre->rtag=1;}pre=current;//前驱跟上,当前指针向前遍历creatInThread(current->rightChild, pre);//递归,右子树线索化

}; 80

§6.4 Threaded Binary Tree3. Operation(Acceleration)(1) Find the Inorder Precursor and Successor of *p (in Inorder

Threaded Tree)

① Find the Inorder Successor of *p i) 若*p的右子树空,则p->rchild为右线索,直接指向*p的中序后继

ii)若*p的右子树非空(rtag为0),则*p的中序后继必是其右子树中第一个中序遍历到的结点,其特征是:从*p的右孩子开始,沿其左链往下找,直至找到一个没有左孩子的结点为止,不妨称其为右子树中“最左下”的结点。

这里k≥ 1, Rk不一定是叶子,其右子树可为空,可非空。

Algorithm

请自己给出找给定结点*p的中序后继算法。时间O(h),快于无线索的二叉树。

p

81

§6.4 Threaded Binary Tree

② Find the Inorder Precursor of *p∵中序是对称序,其方法与①完全对称

i) 若*p的ltag = 1,则中序前驱为lchild

ii)若*p的ltag = 0,则中序前驱是*p的左子树中“最右下”的结点。

Acceleration Effect在普通二叉树中,找*p中序后继:

对于ii)同样有效:O(h)对于 i)就必须从根开始遍历。

∵有线索是直接从线索找到O(1)。但线索一般“向上”指向其祖先,而二叉树中无向上的链接,只能从根开始遍历得到,最坏情况O(n)。

82

§6.4 Threaded Binary Tree(2) Find the Postorder Precursor and Successor of *p (in Postorder Threaded Tree 后序前驱与后继)

① Find the Postorder Precursor of *p (易)

i) 若*p的ltag = 1(左子树为空),则后序前驱为p->lchild

ii)若*p的ltag = 0(左子树非空),则后序前驱为p的左孩子或右孩子

∵根是在遍历左右子树L和R之后被访问

∴*p的前驱必是L和R中最后一个遍历到的结点

if (p的右孩子非空) then

return p->rchild; // 后序前驱为p的右孩子

else

return p->lchild; //后序前驱为p的左孩子

② Find the Postorder Successor of *p (难)(见右图)

i) 若*p为根,无后继,返回NULL

ii) 若*p是其双亲右子,则*p的后序后继是双亲

iii)若*p是其双亲左子,但*p无右兄弟,则*p的

后序后继亦为双亲

83

§6.4 Threaded Binary Tree

② Find the Postorder Successor of *p (续)

iv)若*p是其双亲左子,但*p有右兄弟,则*p的

后序后继是其右兄弟子树中1st后序遍历到的结点,

它是该子树中“最左下的叶结点”

结论:找后序前驱易

找后序后继难,因为:

只有*p的右子树为空(rtag = 1)时,p->rchild是线索,可直接找到;

否则,一般须涉及*p的双亲,故仅给出*p时,须从根遍历。

(3) Find the Preorder Precursor and Successor of *p

类似于后序的情况分析

讨论: 找前序前驱难(涉及双亲)找前序后继易

84

§6.4 Threaded Binary Tree(4) Traversal of Threaded Binary Tree

遍历某次序的线索二叉树,只要从该次序下的开始结点出发,反复找其后继直至终端结点为止。 Inorder

找开始结点(最左下结点),找当前结点中序后继,直至终端结点(p->rchild = NULL) 头结点的右指针指向开始结点较方便

Preorder找开始结点(根),找当前结点的前序后继,直至终端结点

(p->rchild = NULL) 头结点的右指针指向终端结点较方便 Postorder

找终端结点(根),找当前结点的后序前驱,直至开始结点

(p->lchild = NULL),得到的是后序序列的逆序列

头结点的右指针指向开始结点较方便

Time:仍为O(n),但因为非递归,略快于递归的方法

As for Traversal 前序线索树中,只需保留右线索树即可

中序线索树中,保留左、右线索之一均可

后序线索树中,只需保留左线索即可

2017/11/2

15

§6.5 Tree and Forest

A

JIHGFE

DCB

A

JIHGFE

DCB

A

J

I

H

GF

E

D

C

B

=> =>

1. Transformation among Tree, Forest and Binary Tree① Tree Binary Treeevery node in tree has many children every node in binary tree has two childrenthe eldest son and right brother left and right children in binary tree

the eldest son of node X is its left child, the right brother of node X is its right child.

every node just keeps the line with its eldest son connect lines between all brother nodes

86

§6.5 Tree and Forest1. Transformation among Tree, Forest and Binary Tree

② Forest Binary Tree transform all trees into binary trees (root doesn’t have

right brother, so it doesn’t have right child) connect all roots as brothers

87

§6.5 Tree and Forest1. Transformation among Tree, Forest and Binary Tree

③ Binary Tree Tree or Forest assume x is the left child of y, then connect the right child

of x, the right child of its right child, …with y remove all lines between parents and right children

88

§6.5 Tree and Forest1. Transformation among Tree, Forest and Binary Tree

③ Binary Tree Tree or Forest

A

B

C

D E

G

I

A

B C

D

E

G I

89

§6.5 Tree and Forest2. Storage Structure of Tree

① Parent Pointer Notation

∵the parent of every node is unique, so when storing nodes, add a parent domain pointing to parent, it is convenient to express by utilizing vector.

characteristics:link up, the parent of root is -1it is easy to find specified parent (O(1)) and ancestors (O(h))traversal of the array O(n) is necessary to find specified children and descendants type declaration(omit)

A B DC E F G H I J …

-1 0 00 1 1 2 3 3 3 …

0 1 32 4 5 6 7 8 9 10 size -1

data

parent

Fig 6.5 -1对应

A

JIHGFE

DCB

90

② Children Linked List Notation k-ary tree (k叉树) is denoted by k-fork linked list (k叉链表),

which will lead to the waste of space∵edges of tree n-1 ∴null pointers kn-(n-1)=n(k-1)+1

set degree domain, the lengths of nodes are different, it is inconvenient to operate

Children Linked List:set a Children Linked List for every node, put nodes and head pointers of corresponding ChildrenLinked Lists in an array

A

JIHGFE

DCB

2017/11/2

16

2. Storage Structure of Tree② Children Linked List Notation(续) characteristics:it is easy to find the children and descendants

of a node (it is easy to find downward)it is hard to find the parent and ancestors of a node (it is hard to find upward)

parent-children linked list notationadd parent domain in children linked list

this method combines the advantages of parent linked list and children linked list, it is easy to find upward and downward type declaration(omit)

③ Children-Brothers Linked List Notationtree binary tree, the node relationship is indicated by the leftmost child and right brothers

equivalent to Binary Linked List92

§6.5 Tree and Forest

3. Traversal of Tree and Forest① Preorder Traversal of Tree 先序遍历树

visit the root of the tree first, then traverse everysubtree of the root in preorder successively② Postorder Traversal of Tree 后序遍历树

first, traverse every subtree of the root in postordersuccessively, then visit the root of the tree③ Preorder Traversal of Forest 先序遍历森林

④ Postorder Traversal of Forest (Inorder Traversal)后序遍历森林

93

§6.6 Huffman Tree and It's Application

e.g. Programme Converting Centesimal System (百分制)into Five-Grade Marking System (五分制)

Code:if ( 60) b="bad";

else if ( 70) b="pass";

else if ( 80) b="general";

else if ( 90) b="good";

else b="excellent";

a

a

a

a

分数 0-59 60-69 70-79 80-89 90-100

比例数 0.05 0.15 0.40 0.30 0.1094

§6.6 Huffman Tree and It's Applicatione.g. Programme Converting Centesimal System (百分制) into Five-GradeMarking System (五分制)

if ( 60) b="bad";

else if ( 70) b="pass";

else if ( 80) b="general";

else if ( 90) b="good";

else b="excellent";

a

a

a

a

a<60

不及格

中等

及格

a<70

a<80

a<90

良好 优良

Y

Y

Y

Y

N

N

N

N

a<80

a<70 a<90

a<60

不及格 及格

中等 良好 优良

Y

Y

N

Y

YN N

N

1

:

:

n

i i ii

i

WPL w l w

l

i

i

第 个叶子的权(实数)

第 个叶子的路径长度95

§6.6 Huffman Tree and It's Application§6.6.1 Optimal Binary Tree1. Concepts Path Length of Node:the amount of edges passed from the

root to current node Path Length of Tree:the sum of path lengths of all nodes

(when the node numbers are the same, the path length of complete binary tree is the shortest)

Weighted Path Length of Nodes:the weight Wi of the node × the path length li of node

Weighted Path Length of Tree (actually, is weighted external path length):the sum of weighted path lengths of all leaves

§6.6.1 Optimal Binary Tree Optimal Binary Tree (Huffman Tree)in all of the binary trees which are composed of leaves whoseweights are w1,w2,…,wn, the optimal binary tree has thesmallest WPL.For Example n=4,{a:7, b:5, c:2, d:4}

if the weights of leaves are the same, complete binary tree definitely is optimal binary tree, otherwise, which is not sure.

§6.6 Huffman Tree and It's Application

2017/11/2

17

§6.6.1 Optimal Binary Tree 2. Build Optimal Binary Treeapparently, larger weight should be closer to the root, Huffman firstly proposed the construction method:1) Initial Forest:make a forest F={T1,T2,…,Tn} containing nbinary trees according to n given weights {w1,w2,…,wn},among which Ti has only one root (also is a leaf) node, whoseweight is wi;2) Merge:choose two binary trees whose weights of the rootsare the smallest in F, (if more than two, choose at random) asleft and right child, and merge them as a new tree, the weightof new root is the sum of the weights of these two nodes.

3) as for new forest F repeat 2), until only one tree left.98

§6.6 Huffman Tree and It's Application§6.6.1 Optimal Binary Tree2. Build Optimal Binary Tree Storage Structure

#define n 100 // 叶子数

#define m 2*n-1 // 结点总数

typedef struct {float weight; // 权,不妨设≥0int lchild, rchild, parent; // 指针

} HTNode;

typedef HTNode HuffmanTree[m];

parent域作用:找双亲结点

为-1时表示根,区分根与非根

Build Algorithm

99

§6.6.1 Optimal Binary Treevoid CreateHuffmanTree (HuffmanTree T) { // 构造最优树,根为T[m-1]

int i, p1, p2;

InitHuffmanTree(T); // 初始化, 将2n-1个结点的3个指针置空(-1),权置为0

InputWeight(T); // 输入n个叶子(根)的权存于T[0..n-1]中,初

//始化森林F0中的根权

for (i = n; i < m; i++){ // 对F中的树合并n-1次,新根依次放入T[i]中,最终

//根为T[m-1]SelectMin(T, i-1, &p1, &p2); // 在当前森林T[0..i-1]的所有结点中,选权

//最小和次小的两个根结点T[p1]和T[p2]作为合并对象,0≤p1,p2≤i-1T[p1].parent = T[p2].parent = i; // 合并产生的新根为T[i]T[i].lchild = p1;T[i].rchild = p2;T[i].weight = T[p1].weight + T[p2].weight

}}算法中用到的三个函数略

例1:以7,5,1,4,8,10,20这7个权值构造huffman树 100

Step 1: F={7, 5, 1, 4, 8, 10, 20}Step 2: F={7, 5, 5, 8, 10, 20}Step 3: F={7, 10, 8, 10, 20}Step 4: F={15, 10, 10, 20}Step 5: F={15, 20, 20}Step 6: F={35, 20}

1 4

55

10

7 8

1510

20

20

35

55

WPL: 10*2 + 5*3 +1*4 + 4*4 +7*3+ 8*3 + 20*2 = 140

101

T[0..12] 0 1 2 3 4 5 6 7 8 9 10 11 12初始森林:7,5,1,4,8,10,201st合并: 7,5,1,4,8,10,20, 52nd合并:7,5,1,4,8,10,20, 5,103rd合并: 7,5,1,4,8,10,20, 5,10,154th合并: 7,5,1,4,8,10,20, 5,10,15,205th合并: 7,5,1,4,8,10,20, 5,10,15,20,356th合并: 7,5,1,4,8,10,20, 5,10,15,20,35,55

55

20 35

10 10

55

1 4

15

7

20

8

§6.6.1 Optimal Binary Tree2. Build Optimal Binary Tree Algorithm Characteristics

① there are n trees in the very beginning, each tree has only one isolated node

② Merge: merge once, remove a tree, so only need n-1 timesmerge once, generate a new node, whose degree is two, sofinally, Huffman Tree has 2n-1 nodes:

actually, in any strictly binary trees, the amount of all nodes is 2n-1 when there are n leaves.

§6.6 Huffman Tree and It's Application

2 1 ( )n

n1 2

n 1 2

个叶子个结点 无 度结点 严格的 叉树

- 个度为 的结点

2017/11/2

18

103

§6.6.1 Optimal Binary Tree

55

20 35

10 10

55

1 4

15

7

20

8

7 9 -1 -1

5 8 -1 -1

1 7 -1 -1

4 7 -1 -1

8 9 -1 -1

10 10 -1 -1

20 11 -1 -1

5 8 2 3

10 10 1 7

15 11 0 4

20 12 5 8

35 12 9 6

55 -1 10 11

weight parent lchild rchild

0

1

2

3

4

5

6

7

8

9

10

11

12

weights:7,5,1,4,8,10,20

T[0..12]的最终存储状态

Huffman树的类定义

#include “heap.h”const int DefaultSize=20;//缺省权值集合大小struct HuffmanNode//树结点的类定义{

float data;//结点数据HuffmanNode *leftChild, *rightChild, *parent;//左、右子女和父结点指针HuffmanNode():leftChild(NULL),rightChild(NULL),parent(NULL){ } //构造函数HuffmanNode(float elem, HuffmanNode *left=NULL, HuffmanNode *right=NULL, HuffmanNode *pr=NULL):data(elem), leftChild(left), rightChild(right), parent(pr){}bool operator <=(HuffmanNode &R){return data<=R.data;}bool operator>(HuffmanNode &R){return data>R.data;}

};

105

class HuffmanTree//Huffman树类定义{public:

HuffmanTree(float w[], int n);//构造函数~HuffmanTree(){deleteTree(root);}//析构函数

protected:HuffmanNode *root;//Huffman树的根void deleteTree(HuffmanNode *t);//删除以t为根的子树void mergeTree(HuffmanNode &ht1, HuffmanTree &ht2,HuffmanNode *&parent);//合并二叉树

};

106

构造Huffman树的算法,在算法中使用了一个最小堆,利用它组织森林并从中选择根节点权值最小和次小的两棵树。

HuffmanTree::HuffmanTree(float w[], int n){//给出n个权值w[1]~w[n],构造Huffman树。

minHeap hp;//使用最小堆存放森林HuffmanNode * parent, first, second, work;for(int i=0; i<n; i++)//森林各棵树初始化{

work.data=w[i]; work.leftChild=NULL;work.rightChild=NULL; work.parent=NULL;hp.Insert(work);//插入最小堆中

}

107

for(i=0; i<n-1; i++){//做n-1趟,形成Hufman树

hp.RemoveMin(first);//选择根的权值最小的树hp.RemoveMin(second);//选择根的权值次小的树merge(firsr, second, parent);//合并hp.Insert(* parent);//重新插入到最小堆中

}

root=parent;//建立根结点};

108

void HuffmanTree::mergeTree(HuffmanNode &bt1, HuffmanNode &bt2, HuffmanNode *&parent){

parent=new Huffman Node;parent->leftChild=&bt1;parent->rightChild=&bt2;parent->data=bt1.root->data+bt2.root->data;bt1.root->parent=parent;bt2.root->parent=parent;

};

2017/11/2

19

109

§6.6.2 Huffman Coding1. Concepts Data Compressioncan compress 20%~90% of the data file, compressionefficiency depends on the file characteristics Encoding and Decoding

Coding Scheme(For Character Set)Example 2: C = {a, b, c, d, e, f}, assume there are a hundredthousand characters in data file, |C|=6

save 25% space

a b c d e f 编码总长

频度(万) 4.5 1.3 1.2 1.6 0.9 0.5

定长 000 001 010 011 100 101 30万

变长 0 101 100 111 1101 1100 22.4万

Fixed Length Coding:the length of binary code is⌈log2|C|⌉ Variable Length Coding:Ambiguity(二义性) may exist

when people decode it

例如:设E,T,W编码为00, 01, 0001

解码时对0001串有两种方式:ET, W

cause of the problem —— the code of E is the prefix of the

code of W

Prefix Encoding

in character set, the code of any character is not the prefix of the

code of any other characters.

obviously, Fixed Length Code is Prefix Code

Optimal Prefix Encoding (Huffman Coding):the prefix

which has the best compression effect

§6.6.2 Huffman Coding

111

① Dynamic Coding:对给定文件,先统计字符集C = {c1,c2,…,cn} 中各字符出现的频度fi, 据此设计编码,设ci的码长为li,则编码文件总长度:

—— 使文件编码总长最短的前缀码是最优前缀码

对同一字符集表示的不同文件,编码方案不同,即根据文件特征动态编码。

特点: 费时,效果最佳

② Statistical Coding:无需每次压缩前均统计Ci的频度,而是对定义在相同字符集上的大量文件进行统计,得出每个字符Ci 出现的概率pi,据此编码,则平均码长为:

—— 平均码长最短的前缀码为最优前缀码

例:例2中a~f 出现的概率为:0.45, 0.13, …, 0.05, 平均码长为2.24,优于定长编码 (平均码长为3)。

characteristics:

1

n

i ii

f l

all files use the same code, timesaving

as for different files, the effects are different

1

n

i ii

p l

112

§6.6.2 Huffman Coding

2. Encoding Algorithm

Idea of Huffman Coding Algorithm

solve the optimal prefix code by employing Huffman Tree

Step1:use character ci as a leaf,pi (or fi) as the weight of ci,to build Huffman Tree

Step2:mark left and right branch of the tree as 0 and 1respectively, connect numbers on the route from root toleaves successively, as the code of current leaf (character).

Example

113按算法建立的Huffman树唯一

114

§6.6.2 Huffman Coding Is the code above the optimal prefix code?

① Optimal

∵ 叶子的码长 = 叶子的路径长度li

∴ 既是平均码长,又是二叉树的WPL

即 Huffman树是WPL最小的二叉树 => 平均码长最小

② Prefix Code

∵ 树中任一叶子不可能是其它叶子的祖先

∴ 每个叶子编码不可能是其它叶子编码的前缀

3. Algorithm Implementation (For Character Set, i.e. Leaf Set)

typedef struct {

char ch; // 放字符

char bits[n+1]; // 放位串‘\0’结束,码长不会超过n

} CodeNode; // 存放Huffman编码的结点

typedef CodeNode HuffmanCode[n];

1

n

i ii

p l

2017/11/2

20

115

void HuffmanCoding (HuffmanTree T, HuffmanCode H) {

// 根据哈夫曼树T求哈夫曼编码表Hint c, p, i; // c和p分别指示树T中孩子和父亲的位置

char cd[n+1]; // 临时存放编码

int start; // 指示编码在cd中的起始位置

cd[n] = ‘\0’; // 从后往前放编码

for (i = 0; i < n; i++){ //依次求叶子T[i]的编码 0 ≤ i ≤ n-1H[i].ch = getchar();//读入叶子T[i]对应的字符,若建树时有字符则无需读入

start = n;c = i; //从叶子T[i]上溯至根,逆向求编码

while((p = T[c].parent) >= 0) { // 到根为止

if (T[p].lchild == c)cd[--start] = ‘0’; // 若T[c]是T[p]的左子树生成代码0

else cd[--start] = ‘1’; // 否则生成代码1 c = p; // 继续上溯

}strcpy(H[i].bits, &cd[start]); // 复制编码位串

} // endfor } // 时间: O(n.h)

116按算法建立的Huffman树唯一

117

§6.6.2 Huffman Coding4. Application Scenarios (Compression and Decompression of Data Files)

① Compression of Data Files (Encoding Files)

for (依次从f1中读入字符c) {

在Huffman编码表H中,找H[i].ch = c

将c转换为H[i].bits写入压缩文件f2中;

// 按bits0,1串写入“位”,设f2是二进制文件

}② Decompression and Decoding (Decoding Compressed Files)

for (依次读入f2中的位串) { // 直至文件结束

从Huffman树根T[m-1]出发

若当前读入0,走向左孩子,否则走向右孩子;

若到达叶子T[i],便译出字符H[i].ch写入还原文件中,然后

重新从根出发译码

}Note: 实际压缩与解压时,编码的0/1位串,不是字符串,即写入压缩文件中的是“位” 118

§6.7 Backtracking Method and Search Tree

1. Thought of Backtracking Method

有一类问题,需要找出它的解集合,或要求找出满足某些约束条件下的最优解,最简单的方法是回溯法。

所谓回溯就是走回头路,即在一定的约束条件下试探地搜索前进,若前进中受阻,则回头另择道路继续搜索(搜索路线是一棵树)

2. n-Queens Puzzle (Gauss 1777-1855 德国数学家) 高斯8后问题 (1850提出),即在8×8国际象棋棋盘上,

安放8个皇后,要求彼此互不攻击,有多少个解,这些解的格局如何?

他本人未解决此问题

原因: 种格局,92个解(包括对称解)8 3264

64!2

8!56!C

119

§6.7 Backtracking Method and Search Tree Attack (Constraint Condition)two queens on the same row, column, diagonal, will attack each other

i+j: 135 degrees diagonal:when elements are on the same diagonal, the sums of column numbers and row numbers are the same (2n-1) 0~2n-2j-i: 45 degrees diagonal:when elements are on the same diagonal, the differences between column numbers and row numbers are the same (2n-1) –(n-1),…,0,…,n-1 120

§6.7 Backtracking Method and Search Tree Backtracking Method

put queens one by one from the first line, in every line, from the first column, try whether current position is safe, put a queen if current position is safe, if all positions in one line are not safe, then backtrack to last line and reset

将上述求解过程中棋盘状态的每一步变化用树来表示,则

可用4叉树表示(如书上Fig6.29),该树反映了状态空间中搜

索过程,不满足约束条件的结点不再生长(即被剪枝)。先序遍历该树

2017/11/2

21

121

§6.7 Backtracking Method and Search Tree n-Queen Algorithm

设try[0..n-1]存放解,下标为行,值为列,即:设try[i]=j,则(i, j)表示棋盘上第i行,第j列存一皇后,逐行放置,每行只有一皇后故可不考虑行冲突,只要考虑列和2条对角线冲突。

void Queens(i, col, diag45, diag135){ //i, col, diag45, diag135为值参

// 全局量try进入此处时,部分解try[0..i]已求出,col,diag45,diag135

// 是集合,初始调用为Queens(-1, Ф,Ф, Ф)

if (i == n-1)

print try[0..n-1]; // 输出一个解

else // 试求部分解try[0..i+1],即在(i+1)行上放皇后

for (j = 0; j < n; j++) // 试探在第(i+1)行上放皇后

if (j col && j-(i+1) diag45 && (i+1)+j diag135) {

// (i+1, j)位置安全

try[i+1] = j;

Queens(i+1, col∪{j}, diag45∪{j-i-1}, diag135∪{i+j+1});

} // endif

} // 回溯过程要跟踪执行过程才能发现

122

§6.7 Backtracking Method and Search Tree n-Queen Algorithm

the implementation process of the algorithm above is the state tree (preorder traversal) in Fig 6.29

Improvementwe can set the Boolean array (all initial values are false)to test security in practical algorithm

② Put Queens (i+1, j)

令:col[j] = true, 表示第j列已有皇后

diag45[(n-1)+j-(i+1)]=true,表示该对角线上已有皇后

// 移位n-1

diag135[(i+1)+j]=true,表示该对角线上已有皇后

② Security Test

if (!col[j] && !diag45[n-i+j+2] && !diag135[i+1+j])

Note: 用数组要注意它们不是值参,因此可将其说明为结构,内含数组

123

class Queens {public:

Queens(int size);bool is_solved( ) const;void print( ) const;bool unguarded(int col) const;void insert(int col);void remove(int col);int board_size;

private:int count;bool col_free[max_board];bool upward_free[2 * max_board − 1];bool downward_free[2 * max_board − 1];int queen_in_row[max_board]; // column number of queen in each row

}; 124

构造函数

Queens :: Queens(int size)/* Post: The Queens object is set up as an empty configuration on a chessboard with size squares in each row and column. */{

board_size = size;count = 0;for (int i = 0; i < board_size; i++)

col_free[i] = true;for (int j = 0; j < (2 * board_size − 1); j++)

upward_free[j] = true;for (int k = 0; k < (2 * board_size − 1); k++)

downward_free[k] = true;}

125

void Queens :: insert(int col)/* Pre: The square in the first unoccupied row (row count) and column col is not guarded by any queen.Post: A queen has been inserted into the square at row count and column col; count has been incremented by 1. */{

queen_in_row[count] = col;col_free[col] = false;upward_free[count + col] = false;downward_free[count − col + board_size − 1] = false;count++;

}

126

bool Queens :: unguarded(int col) const/* Post: Returns true or false according as the square in the first unoccupied row(row count) and column col is not guarded by any queen. */{

return col_free[col]&& upward_free[count + col]&& downward_free[count − col + board_size − 1];

}

2017/11/2

22

§6.8 Counting of Trees question:how many kinds of different forms are

there in a binary tree with n nodes? 二叉树相似:

T和T’相似:

指形态相同,不考虑结点中数据是否相同,否则为树等价

counting problem of binary tree:solve the number of binary trees with n nodes, i.e. bn, which are not similar between any two of them.

①二者皆空,否则②二者不空时,它们的左右子树相似

General Situation:

we can solve the solution of this recurrence formula employing thegenerating function is(textbook):

• Problem of Counting of Treesthe number of tree forms with n nodes

∵after the tree was converted into a binary tree, the root doesn’t have right subtree

• can traversal sequence uniquely determine a binary tree?

• when a binary tree is determined, its three traversal sequences are uniquely determined

• on the contrary, can traversal sequence uniquely determine a binary tree?

0

1

10

1n

n i n ii

b

b bb n 1

2

1

nn

n

Cb

n

1n nt b

① Preorder Sequence(or Postorder Sequence)+Inorder Sequence of a binary tree can uniquely determine this binary tree例:已知某二叉树的前序序列:ABCDEFG,中序序列:CBEDAFG,求对应的二叉树。

① Preorder Sequence+Postorder Sequence can’t uniquely determine a binary tree例: 前:ABC

后:CBA

③ of course, any one of the traversal sequences can’t uniquely determine a binary tree

§6.8 Counting of Trees