+ All Categories
Home > Documents > Design Patterns for Self-Balancing Trees

Design Patterns for Self-Balancing Trees

Date post: 04-Jan-2016
Category:
Upload: tyrone-bean
View: 30 times
Download: 1 times
Share this document with a friend
Description:
Design Patterns for Self-Balancing Trees. Dung “Zung” Nguyen Stephen Wong Rice University. Motivations. Classic self-balancing tree structures 2-3-4 tree (see next slide) red-black tree (binary tree equivalent of 2-3-4 tree) B-tree (generalized 2-3-4 tree) - PowerPoint PPT Presentation
Popular Tags:
24
Design Patterns for Self-Balancing Trees Dung “Zung” Nguyen Stephen Wong Rice University
Transcript
Page 1: Design Patterns for Self-Balancing Trees

Design Patterns for Self-Balancing Trees

Dung “Zung” Nguyen

Stephen WongRice University

Page 2: Design Patterns for Self-Balancing Trees

Motivations Classic self-balancing tree

structures– 2-3-4 tree (see next slide)– red-black tree (binary tree equivalent

of 2-3-4 tree)– B-tree (generalized 2-3-4 tree)– Difficult and complex. Where’s the

code? What’s the proper abstraction?– Need to decouple algorithms from

data structures.

Page 3: Design Patterns for Self-Balancing Trees

A 2-3-4 Tree is…

A

A B

A B C

Empty

Non-Empty, in 3 possible states:

1-State: 1 data element + 2 sub-trees.

3-State: 3 data elements + 4 sub-trees.

2-State: 2 data elements + 3 sub-trees.

0-State: no data element + no sub-trees.

Page 4: Design Patterns for Self-Balancing Trees

Variant vs. Invariant Operations

Self-balancing insertion is not an intrinsic (invariant) operation of a tree.

What are the invariant operations?– Gettors & Constructors.– Constructive and Destructive operations:

Constructive: Splice a tree into another.Destructive: Split a tree into a 2-state.

Page 5: Design Patterns for Self-Balancing Trees

B

Splittin’ and Splicin’

A CA B C

B

A B C

A C

B

Split Up:Splice:

Page 6: Design Patterns for Self-Balancing Trees

Structural Operationst1

-10 0 10-20 20

t1.splitUpAt(1)

-10

0 10-20 20

t2

β γα

t1.spliceAt(1, t2)

-10 0 10-20 20β γα

t1.splitDownAt(1)

-10

0 10-20 20

Page 7: Design Patterns for Self-Balancing Trees

Con/De-structiont1

10

t2

t1.splitUpAt(0)

10

t1.splitDownAt(0)

t2.spliceAt(0, t1)

10

Page 8: Design Patterns for Self-Balancing Trees

Visitor Design Pattern

Invariant: Hosti calls casei of the visitor.

AHostexecute(v)

AVisitor+case1()+case2()+case3()

Host1 Host2 Host3

VisitorA VisitorB

Fixed # of methods fixed # of hosts

Page 9: Design Patterns for Self-Balancing Trees

Generalized Visitors

Invariant: Hosti calls caseAt(i) of the visitor.

AHostexecute(v) AVisitor

+caseAt(int i)Host1 Host2 Host3

VisitorA VisitorB

Page 10: Design Patterns for Self-Balancing Trees

TreeN and Algorithms

Page 11: Design Patterns for Self-Balancing Trees

toString() Algorithmpublic class ToStringAlgo implements ITreeNAlgo { // Constructors omitted

public Object caseAt(int idx, TreeN host, Object key) { switch(idx) { case 0: { return "[ ]"; } default: { String sData= "", sTrees=""; for(int i = 0;i<idx;i++) {

sData += host.getDat(i)+" "; sTrees += host.getChild(i).execute(toStringHelp,"| ")+"\n";

} sTrees += host.getChild(idx).execute(toStringHelp," ").toString(); return sData +"\n"+sTrees; } } } ITreeNAlgo toStringHelp = …see next slide….}

Empty Tree

Non-Empty Tree

“Prefix” data

Page 12: Design Patterns for Self-Balancing Trees

ToString() Helperprivate final static ITreeNAlgo toStringHelp = new ITreeNAlgo() { public Object caseAt(int idx, TreeN host, Object prefix) { switch(idx) { case 0: { return "|_[ ]"; } default: { String sData= "", sTrees=""; for(int i = 0;i<idx;i++) { sData += host.getDat(i)+" "; sTrees += prefix + (String) host.getChild(i).execute(this, prefix+"| ")+"\n"; } sTrees += prefix + host.getChild(idx).execute(this, prefix+" " ).toString(); return "|_ "+sData +"\n"+sTrees; } } }};

Empty Tree

Non-Empty Tree

“Prefix” data

Page 13: Design Patterns for Self-Balancing Trees

Vertical Data Transport

-10 0 10-20 20

5

-10 0 10-20 20

5

-10 0 10-20 205

Split up Splice

Collapse/Splice

Split-down

No net height change except at root and leaves!

Page 14: Design Patterns for Self-Balancing Trees

Command Design Pattern

ICommand+Object apply(Object inp)

Command1 Command2 Command3

Performs a task.

No specified semantic!

Well-defined, but unrelated semantics.

Invoker invokes

Page 15: Design Patterns for Self-Balancing Trees

Insertion Heuristics Insertion must take place at the leaf. Tree must grow only at the root.

Must transport data from the leaves to the root

without affecting the height balance.

Page 16: Design Patterns for Self-Balancing Trees

Problem: If a child node is too wide, it needs to split up and splice into its parent, but…

The child node does not know where to splice into its parent

The child does not even have a reference to its parent.

Solution: Pass a command (lambda) forward from the parent to the child during the recursive call.

Page 17: Design Patterns for Self-Balancing Trees

class SplitUpAndApply implements ITreeNAlgo { int _order; public SplitUpAndApply(int order) { _order = order;} public Object caseAt(int i, TreeN host, Object param) { if(i <= _order) return host;

else { host.splitUpAt(i / 2);

return ((ILambda)param).apply(host); } }}

Split-up and Splice (Apply)Max width of node

Not too wide? no-op

Too wide? Split up then apply lambda

The lambda splices this child into its parent.

Page 18: Design Patterns for Self-Balancing Trees

Insertion Algorithm Find insertion point at the leaf and splice new

data in. Use Split-and-Apply visitor to transport excess

data upwards.– Visitor passed as parameter to recursive call.– Non-root: split-and-splice– Root node: split-and-no-op will cause entire

tree to grow in height.– Abstract the splice/no-op as a command

passed to the visitor!

Page 19: Design Patterns for Self-Balancing Trees

Splice into parent!

Insertion Dynamics

20

405 30

25

λ110

15 λ2

25

Compare and create splicing

lambda

Compare and create splicing

lambda

Insert here!

Too wide!Split up

Too wide!Split up

Splice into parent!Send lambda to child!

Send lambda to child!

2 elements/node max

Page 20: Design Patterns for Self-Balancing Trees

public Object caseAt(int s, final TreeN host, final Object key) { switch(s) { case 0: { return host.spliceAt(0, new TreeN((Integer) key)); } default: { host.execute(new ITreeNAlgo() { public Object caseAt(int s_help, final TreeN h, final Object cmd) { switch(s_help) { case 0: { return ((ILambda)cmd).apply(new TreeN((Integer)key)) ;} default: { final int[] x={0}; // hack to get around final

for(; x[0] < s_help; x[0]++) { // find insertion location int d = h.getDat(x[0]).intValue(); if (d >= ((Integer)key).intValue()) { if (d == ((Integer)key).intValue()) return h; // no duplicate keys else break; } } h.getChild(x[0]).execute(this, new ILambda() { public Object apply(Object child) { return h.spliceAt(x[0], (TreeN) child); } } );

return h.execute(splitUpAndSplice, cmd); } } } }, new ILambda() { public Object apply(Object child){ return host; }} ); return host; } } }

Empty tree? Splice new tree in here!

Non-Empty tree? create a recursive helper

Empty tree? splice into parent

x[0] has the splice location

Fin

d t

he

inse

rtio

n/s

pli

ce

loca

tion Recur into the child, passing

on the splicing lambda

Run the given splicing lambda

Root has no parent to splice into

The beauty of closures!

Page 21: Design Patterns for Self-Balancing Trees

Deletion Heuristics

Deletion only well-defined at leaf. Data might exist anywhere in the tree. Tree can only shorten at root.

Must transport data from the root to the leaves and

from the leaves to the rootwithout affecting the height balance.

Push “candidate” data down from the root to the leaves.

Bubble “excess” data back to the root.

Page 22: Design Patterns for Self-Balancing Trees

Deletion Algorithm Identify candidate data – split down at candidate and collapse with

children.– If root is a 2-node, then tree will shorten.

Data to delete will appear as 2-node below leaves.

Use Split-and-Apply to transport excess data upwards.

Page 23: Design Patterns for Self-Balancing Trees

Deletion Dynamics

20

10 30 40

5 2515 35 45

Remove “30”2 elements/node max

Split-down candidateelement and collapse

with children

Delete it!

Split-up and spliceas needed

Page 24: Design Patterns for Self-Balancing Trees

Conclusions Proper abstraction leads to

– Decoupling– Simplicity– Flexibility & extensibility

Generalized Visitors open up new possibilities. Self-balancing trees teach

– Abstract decomposition– Design patterns– Component-frameworks– Lambda calculus– Proof-of-correctness & complexity analysis


Recommended