trees --part i

78
Trees --Part I Lai Ah Fur

Upload: aliza

Post on 05-Jan-2016

40 views

Category:

Documents


2 download

DESCRIPTION

Trees --Part I. Lai Ah Fur. definition. A tree can be defined recursively as the following: An empty structure is an empty tree If t 1 ,…,t k are disjoint trees, then the structure whose root has its children the roots of t 1 ,…,t k is also a tree. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Trees --Part I

Trees--Part I

Lai Ah Fur

Page 2: Trees --Part I

definition A tree can be defined recursively as the following:

– An empty structure is an empty tree

– If t1,…,tk are disjoint trees, then the structure whose root has its children the roots of t1,…,tk is also a tree.

– Only structures generated by previous two rules are trees.

A tree is a finite set of one or more node such that:– There is a specially node designated node called the root.

– The remaining nodes are partitioned into n>=0 disjoint sets t1,…,tn,where each of the sets is a tree. We call t1,…,tn the subtrees of the root.

Page 3: Trees --Part I

Organize a hierarchical representation of objects.

FOREST: after removing the root, all the subtrees become one of set of the forest

Types: binary tree, binary search tree(BST), AVL tree, Red-Black tree,2-3 tree, 2-3-4 tree, B-tree

Page 4: Trees --Part I

Terms:path,length,level,height

Each node has to reachable from the root through a unique sequence of arcs, called a path.

The number of arcs in a path is called the length of the path.

The level of a node is the the length of the path from the root to the node plus 1, which is the number of nodes in the path.

The height (depth) of a nonempty tree is the maximum level of a node in the tree.

The empty tree is a legitimate tree of height 0. A single node is a tree of height 1 ( a node is both the

root and a leaf).

Page 5: Trees --Part I

Terms (2) DEGREE PARENT/CHILD/SIBLING ANCESTOR/DESCENDANT TERMINAL NODE (LEAF)/

NON-TERMINAL NODE

(internal node) subtree

A

B C

E G H

J K L

M

D

IF

N O

LEVEL=1

LEVEL=5

Page 6: Trees --Part I

Compare the linked list and tree?

Your exercise?

Page 7: Trees --Part I

Binary tree

A binary tree is a tree whose node have two children(possible empty), and each children is designated as either a left child or a right child.

A complete binary tree: all nonterminal nodes have both their children, and all leaves are at the same level. There are at most 2i nodes at level i+1.

A full binary tree: The tree which has the height k contains 2k-1 nodes.

Page 8: Trees --Part I

Representation of a binary tree

List: (A(B(D()())(E()()))(C()(F()())) Array

link

A

B C

D E F

0 1 2 3 4 5 6 7 8

A B C D E F

Page 9: Trees --Part I

EXCERSIZE

LIST? ARRAY?

(RULE?)A

B C

D E F

G H I

J

Page 10: Trees --Part I

Binary search tree

Also called ordered binary tree For each node n of the tree, all values in its

left subtree are less than value v stored in n, and all values stored in the right subtree are greater than v.

Page 11: Trees --Part I

Binary-search-tree (BST)BST property: Let x be a node in a BST.– If y is a node in the left subtree of x, then key[y] < key[x].– If y is a node in the right subtree of x, then key[x] < key[y].

Tree construction: Worst case: O(n2); average case: O(nlgn), where n is the # of nodes

Operations Search, Minimum, Maximum, Predecessor, Successor, Insert, Delete can be performed in O(h) time, where h is the height of the tree.

˙Worst case: h = -(n); balanced BST: h = -(lgn).˙Can we guarantee h = -(lgn)? Balance search trees!!

Page 12: Trees --Part I
Page 13: Trees --Part I

二元樹的特性

(1)二元樹中 ,階度 (level) 為 i的最大節數是 2i-

1 , i 0≧證明:利用歸納法證明步驟1:樹根是唯一階度為 l 的節點,因此階度

i=l 時最大的節點為 2i-l=2l-l=l步驟2:對所有 j , l j<I≦ ,階度 j 上最大的節數

為 2j-l 。步驟3:由步驟 2 知, i-l 階度上最大的節數為

2i-2 ,而二元樹中每一節的分支度均≦ 2 ,因此階度 i 上最大的節數等於 2 乘以階度 i-l 上的最大節數,也就是 2i-l 。

Page 14: Trees --Part I

(2) 若二元樹的深度為 k ,則此二元樹最多的節數目為 2k-l 。

證明:深度為 k 的二元樹,其最多的節數目等於階度 l 到階度 k 中各階度最大節數的和,亦即

2i-1=20+21+……+2k-2+2k-1

=(2k-1)/(2-1)=2k-1 

Page 15: Trees --Part I

(3)任何一個非空二元樹 T,若終端節點總數為 n0,且分支度等於 2的節點數是 n2,則 n0=n2+1 。

證明: 設 n1 是分支度 (degree) 等於 1 的節點數, n 是總節數,因

為 T 中有節點的分支度都≦ 2 ,所以n=n0+n1+n2--------------------------------------(1) 二元樹中,除了樹根以外,每一個節點都有一個分支

(branch) 指向它,令 B 是分支數。因此 B=n-1---------------------------------------(2)而所有的分支 ( 分支總數 ) 都是由分支度等於 1 或 2 的節點指,故 B=n1+2n2--------------------------------------(3) 由 (2) 與 (3) 得n-1=n1+2n2 代入 (1) 式得n0+n1+n2-1=n1+2n2

移項理可得n0=n2+1

Page 16: Trees --Part I

BST node

public class IntBSTNode { protected int key;protected IntBSTNode left, right; public IntBSTNode() { left = right = null; } public IntBSTNode(int el) { this(el,null,null); }public IntBSTNode(int el, IntBSTNode lt,

IntBSTNode rt) { key = el; left = lt; right = rt; } public void visit() { System.out.print(key + "

"); } }

Page 17: Trees --Part I

Tree traversal

Tree traversal is the process of visiting each node in the tree exactly one time.

Linearizing a tree For a tree with n nodes, there are n!

different traversals. Most of them are useless.

Breadth-first traversal Depth-first traversal

Page 18: Trees --Part I

Breadth-first traversal

Visit each node starting from the lowest (or highest) level and move down (or up) level by level, visit nodes on each level from left to right (or from right to left).

Four possibilities– Result:A,B,C,D,E,F,G,H,I,J

Implementation :– needs a queue.

A

B C

D E F

G H I

J

Page 19: Trees --Part I

Top-down, left to right, Breadth-first traversalpublic void breadthFirst() { IntBSTNode p = root; Queue queue = new Queue(); if (p != null) { queue.enqueue(p); while (!queue.isEmpty()) { p = (IntBSTNode) queue.dequeue(); p.visit(); if (p.left != null) queue.enqueue(p.left); if (p.right != null) queue.enqueue(p.right); } } }

Page 20: Trees --Part I

Depth-first traversal

Three tasks:– V:visiting a node

– L:traversing the left subtree

– R:traversing the right subtree

Six possible ordered depth-first traversals:– VLR VRL LVR RVL LRV RLV

Preorder traversal: VLR Inorder traversal: LVR Postorder traversal: LRV

Page 21: Trees --Part I

EXAMPLE

PREORDER:VLR– A,B,D,G,E,H,C,F,I,J

INORDER: LVR– GDBEHACFJI

POSTORDER: LRV– GDHEBJIFCA

A

B C

D E F

G H I

J

Page 22: Trees --Part I

EXCERCISE

PREORDER:VLR– ?

INORDER: LVR– ?

POSTORDER: LRV– ?

A

B C

D E F

G I J

N

H

LLK

Page 23: Trees --Part I

Preorder (RECURSIVE)

protected void preorder(IntBSTNode p) {

if (p != null) { p.visit(); preorder(p.left); preorder(p.right); } }

Page 24: Trees --Part I

Preorder (ITERATIVE)public void iterativePreorder() { IntBSTNode p = root; Stack travStack = new Stack();if (p != null) { travStack.push(p); while (!travStack.isEmpty()) { p = (IntBSTNode) travStack.pop(); p.visit(); if (p.right != null) travStack.push(p.right); if (p.left != null) travStack.push(p.left);

// left child pushed after right ,to be on the top of the

Stack; } } }

Page 25: Trees --Part I

Inorder (RECURSIVE)

protected void inorder(IntBSTNode p) {

if (p != null) { inorder(p.left); p.visit(); inorder(p.right); } }

Page 26: Trees --Part I

Inorder(iterative)public void iterativeInorder() { IntBSTNode p = root; Stack travStack = new Stack(); while (p != null) { while(p != null) { // stack the right child (if any) if (p.right != null) // and the node itself when going travStack.push(p.right); // to the left; travStack.push(p); p = p.left; } p = (IntBSTNode) travStack.pop(); // pop a node with no

left child while (!travStack.isEmpty() && p.right == null) { // visit it

and all p.visit(); // nodes with no right child; p = (IntBSTNode) travStack.pop(); } p.visit(); // visit also the first node with a right child (if

any); if (!travStack.isEmpty()) p = (IntBSTNode) travStack.pop(); else

p = null; // is over} }

Page 27: Trees --Part I

Postorder (RECURSIVE)

protected void postorder(IntBSTNode p) { if (p != null)

{ postorder(p.left); postorder(p.right); p.visit(); } }

Page 28: Trees --Part I

public void iterativePostorder() { IntBSTNode p = root; Stack travStack = new Stack(); //trace 用堆疊output = new Stack(); // 結果堆疊if (p != null) { // left-to-right postorder = right-to-left preorder LRV

travStack.push(p); while (!travStack.isEmpty()) { p = (IntBSTNode) travStack.pop(); output.push(p); if (p.left != null) travStack.push(p.left); if (p.right != null)

travStack.push(p.right); } //whilewhile (!output.isEmpty()) { p = (IntBSTNode) output.pop(); p.visit(); } } }

Postorder (iterative-1)

Page 29: Trees --Part I

public void iterativePostorder() { BSTNode p = root,q=root; Stack travStack = new Stack(); while ((p != null) { for(;p.left!=null ;p=p.left) travStack.push(p); while ((p != null)&& (p.right==null ||

p.right==q)) { p.visit(); q=p; //q has been visited If (travStack.isEmpty()) return ; p= (BSTNode) travStack.pop(); }//while travStack.push(p); p=p.right; }//while }

Postorder (iterative-2)

q

P

Both has visited

Page 30: Trees --Part I

search

protected IntBSTNode Search(IntBSTNode p, int el)

{ while (p != null) if (el == p.key) return p; else if (el < p.key) p = p.left; else p = p.right; return null; }

Page 31: Trees --Part I

INSERT (BST)

15

4 15

4

2015

NULL

(A)insert 15 (B)insert 4 (c) insert 20

15

4 20

1715

4 20

17

19 15

4 20

17

19(D)insert 17

(E)insert 19 (F)

Page 32: Trees --Part I

CREATE a BST USING INSERT

Given the following integer sequence, please create the BST: 50,67,23,45,87,99,34,12,44,90,100,10,11,35,111

Page 33: Trees --Part I

insertpublic void insert(int el) {IntBSTNode p = root,prev = null; while (p != null) { // find a place for inserting new node;

prev = p; if (p.key < el) p = p.right; else p = p.left; } if (root == null) // tree is empty; root = new IntBSTNode(el);else if (prev.key < el) prev.right = new IntBSTNode(el); else prev.left = new IntBSTNode(el); }

Page 34: Trees --Part I

Delete a node

Delete by merging Delete by copying

Delete 16

Free the spaceDelete 20

Free the space 

Page 35: Trees --Part I

Delete by merging

Make one tree out of the two subtrees of the node, then attach it to the node’s parent

How to merge these subtrees?– Find in the left subtree the node with the greatest value

and make it a parent of the right subtree

– Find in the right subtree the node with the lowest value and make it a parent of the left subtree

Drawback: increase the height of the tree (It is certainly far from perfect!)

Page 36: Trees --Part I

Delete by merging

Delete node

node left

node right

node

Rightmost node of the left subtree

Root

node left

node right

node left

Root

node right

node left

Page 37: Trees --Part I

Delete by merging (example)

Delete 15

Delete 15

Page 38: Trees --Part I

Details of deleting by merging

Page 39: Trees --Part I

Delete by copying

Proposed by Hilbard & Knuth If the node has 2 children, it can be replaced

with its immediate predecessor (or successor)

This algorithm doesn’t increase the height of the tree, but it may cause the unbalanced problem.

Page 40: Trees --Part I

Delete by copying (example)A

B C

D E F

G I J

N

H

MLK

Delete BOther?

A

M C

D E F

G I J

N

H

LK P

P

Page 41: Trees --Part I

Details of deleting by copying

Page 42: Trees --Part I

Deleting node (1)

prev

node

p

prev

node

p

prev

nodep

Case 1

Case 2 if (node.right == null) //node has no right child; node = node.left; else if (node.left == null) //no left child for

node; node = node.right; if (p == root) root = node; else if (prev.left == p) prev.left = node; else prev.right = node;

Page 43: Trees --Part I

Deleting node (2)prev

nodep

previous

tmp

if (node.right != null &&node.right != null){// node has both children; BSTNode tmp = node.left; BSTNode previous = node; // 1. while (tmp.right != null) { // 2. find the rightmost position in the left subtree of node; previous = tmp; // tmp = tmp.right; //} node.key = tmp.key; // 3. overwrite the reference // of the key being deleted; if (previous = = node) // if node's left child's right subtree is null

previous.left = tmp.left;; else previous.right = tmp.left; }…….

prev

nodep

previous

tmp

Page 44: Trees --Part I

exercise Delete 16, 請用三種

做法 insert 28 Design the class of

the node of this BST (java)

20

16 25

10 17 30

5 18 40

35

15

73 13

Page 45: Trees --Part I

Balancing a tree Stream of data: 5,1,9,8,7,0,2,3,4,6 Array of sorted data:0,1,2,3,4,5,6,7,8,9

4

1

0 2

4 4

1

public void balance(BaseObject data[], int first, int last) { if (first <= last) { int middle = (first + last)/2; insert(data[middle]); balance(data,first,middle-1); balance(data,middle+1,last); } }

Drawback: All data must be put in an array beforethe tree can be created.

4

1

0 2

3

7

5 8

6 9

Page 46: Trees --Part I

二元樹的計數 (Counting Binary Tree) n 個節可排成多少個不

同的二元樹?(1)   n=0 或者 n=1 ,祇有

一種二元樹(2)   n=2 時,存在兩種不

同的二元樹。(3)   n=3 時,存在五種不

同的二元樹。

Page 47: Trees --Part I

二元樹的計數 n 個節點所能排成不同二元樹的個數可以

列公式求出:

Page 48: Trees --Part I

中序順序及前序順序決定一個二元樹例:有一個前序順序為: ABCDEFGHI 中序

順序為: BCAEDGHFI 則其相對應的二元樹為何?

解:前序追蹤的第一個字元 A 一定是樹根,再從中序追蹤知在 A 之前的節點 BC 是左子樹,在 A 之後的節點 EDGHFI 是右子樹,由此我們可以大略的建立出其相對應的二元樹形狀。

再由前序追蹤的第二個字元 B 知其為樹根,從中序追蹤知 B 的左子樹是空的,右子樹是C ,因此其進一步結果如下:

同理類推,整個二元樹如下所示:

Page 49: Trees --Part I

一對中序順序 (inorder sequence) 及前序順序(preorder sequence) 可唯一決定一個二元樹。

一對中序順序 (inorder sequence) 及後序順序(postorder sequence) 亦可唯一決定一個二元樹。

一對前序順序 (preorder sequence) 及後序順序(postorder sequence)無法決定唯一一個二元樹

Page 50: Trees --Part I

exercise

有一個前序順序為: ABDEFG 中序順序為: BAEDGF 則其相對應的二元樹為何?

a

b d

e f

g

Page 51: Trees --Part I

中序順序及後序順序決定一個二元樹

INORDER: GDBEHACFJI POSTORDER: GDHEBJIFCA

Page 52: Trees --Part I

QUIZ

有一個後序順序為: CBGHEJFDA 中序順序為: BCAGEHDJF 則其相對應的二元樹為何? PREORDER? Represent the tree using list and array?

有一個前序順序為: ABDGCEHIF 中序順序為: DGBAHEICF 則其相對應的二元樹為何? POSTORDER?

COMPARE : BST AND HEAP

Page 53: Trees --Part I

樹化為二元樹的方法 一般採用“ leftmost-child-next-right-

sibling 方式將樹化為二元樹,其步驟如下:

(1)   將節點的所有兄弟用平行線連接起來。

(2)   刪除掉所有與子點間的鏈結,祇保留與最左子間的鏈結。

(3)   順時針旋轉 45 度。

Page 54: Trees --Part I

樹化為二元樹範例

Page 55: Trees --Part I

樹林 (forest) 化為二元樹的方法 將樹林中的每一個樹利 leftmost-child–

next-right-sibling 法化為二元樹。– 利用上述< i >< ii >方法將各二元樹合併

成一個二元樹。 另法:首先將各樹的樹根由左而右連接

起來。利用 leftmost-child-next-right-sibling 法將其化為二元樹。

例:有三個樹的樹林如下,將其化為二元樹表示之。

解:首先將各樹的樹根連接起來如下所示:接著,利用 leftmost-child–next-right-sibling 方法轉換

Page 56: Trees --Part I

樹林 (forest) 化為二元樹

Page 57: Trees --Part I

THREADED TREE Trees whose nodes use threads are called threaded trees Threads are reference to the predecessors and successors

of the node according to an inorder traversal.( 與 java 的thread 不同 ,which is a light weight process)

Four referencce fields are needed for each node in the tree, but by overloading existing reference fields, left or right references which are references to children can also be used as references to predecessors or successors – Left reference is either a reference to the left child or to

the predecessor– right reference is either a reference to the right child or

to the successor

Page 58: Trees --Part I

Element of the node

(inorder traversal only use successor)

Left predecessor key successor rightLeft predecessor key successor right

•由 predecessor 決定 left 是否為 predecessor reference 或 left reference

Page 59: Trees --Part I

Node of the threaded tree (only 處理successor)

class IntThreadedTreeNode {protected int key;protected boolean successor;//only for successor referenceprotected IntThreadedTreeNode left, right;public IntThreadedTreeNode( ) { left = right = null; successor = false;}public IntThreadedTreeNode(int el) { this(el,null,null);}public IntThreadedTreeNode(int el, IntThreadedTreeNode lt,IntThreadedTreeNode rt) { key = el; left = lt; fight = rt; successor = false;}public void visit( ) { System out print(key + “ “);}}

Page 60: Trees --Part I

Insertion of the threaded tree (only 處理successor)public void threadedInsert(int el) {IntThreadedNode newNode = new IntThreadedNode(el);If (root == null) { // tree is empty root = newNode; return;}IntThreadedNode p = root, prev = null;while (p != null) { // find a place to insert newNode; prev = p; if (el < p.key) p = p.left; else if (!p.Successor) // go to the right only if it is p = p.right; // a descendant, not a successor; else break; // don't follow successor link; } if (el < prev.key) { // if newNode is left child of prev.left = newNode; // its parent, the parent newNode.Successor = true;// also becomes its successor; newNode.right = prev; } else if (prev.Successor) { // if parent of the newNode newNode.Successor = true;// is not the rightmost node, prev.Successor = false; // make parent's successor newNode.right = prev.right; // newNode’s successor, prev.right = newNode;} else prev.right = newNode; // otherwise it has no successory;} //

Page 61: Trees --Part I

Insertion of the threaded tree: Insert 35

60

40

15

77

88 NullNull

35Null newnode

prev

Page 62: Trees --Part I

Inorder of the threaded treepublic class IntThreadedTree {private IntThreadedNode root;public IntThreadedTree( ) { root = null;}protected void threadedInorder( ) {IntThreadedNode prev, p = root;if (p != null) { //process only nonempty trees; while (p.left != null) // go to the leftmost node; p = p.left;while (p !=null) { p.visit( ); prev = p; p = p.right; //go to the right node and only if (p != null && !prev.successor) // if it is a descendant while (p.left != null) // go to the leftmost node, p = p.left; // otherwise visit the successor;

}// while (p !=null) } }

Page 63: Trees --Part I

Example of THREADED TREE

60

40

15

77

88 NullNull

Dangling

Page 64: Trees --Part I

BINARY EXPRESSION TREE (3+4)*(5+6/7)

*

+

3 4

+

5 /

6 7

Page 65: Trees --Part I

由中序式建立算式樹輸入運算式的中序式,建立算式樹 由運算式的中序式來建立算式樹時,必須利用中序式轉換為後序式的過程中,來建立算式樹,而且要使用一個指標堆疊,假設此堆疊為 sopd,則建立算式樹的演算法如下:

1. 在中序轉換為後序的過程中,如果要輸出一個運算元時,則建立一個新節點,儲存此運算元,其左右兩指標欄設定為 NULL ,並且將節點指標 push置入指標堆疊 sopd中。

2. 在中序轉換為後序的過程中,如果要輸出一個運算子時

– 若此運算子之 priority<=Sopr 則由 Sopr pop 出運算子且建立新節點,儲存此運算子,並且由指標堆疊 sopd 中 pop 彈出一個指標,存入新節點的右指標欄,再由 sopd中彈出一個指標,存入新節點的左指標欄,然後將新節點指標再 push 置入 sopd堆疊中。

– 否則直接將此運算子 push 到 Sopr

Page 66: Trees --Part I

4*3+5*8/2-7

null 4 null null 3 null

(1)~(3)

Sopd *Sopr

*

null 4 null null 3 null

Sopd+

Sopr

null 5 null

(4)~(5)

Page 67: Trees --Part I

4*3+5*8/2-7

*

null 4 null null 3 null

Sopd*+

Sopr

null 5 null

null 8 null

*

null 4 null null 3 null

Sopd

null 5 null null 8 null

*

null 2 null

/+

Sopr

(6)

(7)~(8)

Page 68: Trees --Part I

*

null 4 null null 3 null

Sopd

null 5 null null 8 null

* null 2 null

+

Sopr

(9)-1

4*3+5*8/2-7

/

Page 69: Trees --Part I

*

null 4 null null 3 null

Sopd

-Sopr

(9)-2~(10)

4*3+5*8/2-7

null 5 null null 8 null

* null 2 null

/

+ null 7 null

Page 70: Trees --Part I

*

null 4 null null 3 null

Sopd

Sopr

(9)-24*3+5*8/2-7

null 5 null null 8 null

* null 2 null

/

+ null 7 null

-

(11)

Page 71: Trees --Part I

由前序式建立算式樹 如果輸入是運算元,則建立節點儲存運算元,停止往下建樹。

如果輸入是運算子,則建立節點儲存運算子,並且以遞迴方式先往下建左子樹,再建右子樹。

Page 72: Trees --Part I

-+* 4 3 / * 5 8 2 7

*

null 4 null null 3 null

+

-

Page 73: Trees --Part I

Algorithm for 前序式建立算式樹Expnode createtree (Expnode p){ p=new Expnode(); p.key= 輸入內容 ;// 依序 if (operands(p.key)) p.left=p.right=null; else if (operators(p.key)) { p.left=createtree(p.left); p.right=createtree(p.right); } return (p); }//please complete the previous algorithm

Page 74: Trees --Part I

由後序式建立算式樹 如果輸入是運算元,則建立節點儲存,

停止往下建樹。 如果輸入是運算子,則建立節點儲存,

並且以遞迴方式先往右邊建子樹,再往左邊建子樹。

Page 75: Trees --Part I

4 3 * 5 8 * 2 / + 7 -

null 5 null null 8 null

* null 2 null

/

+ null 7 null

- (1)(2)

(3)-(4)

Page 76: Trees --Part I

算式樹求值 以 postorder 方式追蹤算式樹 , 每當追蹤

到一個 operator 及二個 operand, 進行運算– (1) 追蹤到 operand, push into operand_stack– (2) 追蹤到 operator, 由 operand_stack pull 二

個 operand, 進行運算 , 運算 result push into operand_stack

Page 77: Trees --Part I

算式樹求值 example

null 5 null null 8 null

*

null 2 null

-

*

null 2 null null 12 null

/

null 2 null

85

*

40

5,8 12,2 21240

/6

40

-

34

Operand_stack

Page 78: Trees --Part I

Exercise II:建立 binary算式樹 ,求值 Input: 後序式 / 中序式 / 前序式 建立算式樹 算式樹求值 印出其他 order Option: draw this tree