Data Structures

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 94

Modern Programming Concepts in Engineering

Topic 6: Data structures

Matthias Baitsch

Vietnamese-German Universit y
Introduction
A data structure is a particular way of storing and organizing data
in a computer so that it can be used efficiently

Dictionary: How to store millions of words for fast access?


Introduction
A data structure is a particular way of storing and organizing data
in a computer so that it can be used efficiently

Routing: How to store towns and streets to find the shortest


connection?
Introduction

A data structure is a particular way of storing and organizing data


in a computer so that it can be used efficiently

Family tree: Who are the descendants of a certain person?


Introduction

A data structure is a particular way of storing and organizing data


in a computer so that it can be used efficiently

Finite element program: How to access and modify thousands of


nodes and elements.
Introduction

A data structure is a particular way of storing and organizing data


in a computer so that it can be used efficiently
I Different kinds of data structures are suited to different kinds
of applications
I Specific data structures are essential ingredients of many
efficient algorithms, and make possible the management of
huge amounts of data
Introduction

I Two different general types of data structures are


distinguished
I Array structures
I Linked structures
I Array data structures are based on computing the addresses of
data items with arithmetic operations
I Linked data structures are based on storing addresses of data
items within the structure itself
Introduction

I In this topic we are dealing with two types data structures:


I lists and
I trees
I Practically, data structure are implemented as classes
I An instance of a data structure is an object of the data
structure type
I A data structure object stores objects of the same type
Lists

I A list (or sequence) is an ordered collection of elements with a


linear structure

L :=< e0 , e1 , ..., en−1 >


I Lists have an absolute order
I each element has a dedicated index
I as well as a relative order
I Beside the first and the last element, each element has a
predecessor and successor element
Lists
I The elements of a list are objects
I List of String objects

L :=< ”Modern”, ”Programming ”, ”Concepts” >

I List of Integer objects (Fibonacci numbers)

L :=< 0, 1, 1, 2, 3, 5, 8, 13 >

I List of Point objects (polyline)


L :=< p1 , p2 , p3 , p4 , p5 >
Lists
I Two implementation for lists exist
I Array list (absolute order)

I Linked list (relative order)

I Typical operations are


I add an element to the end
I insert an element at a specified position
I set an element at a specified position
I return the element at a specified position
I remove the element at a specified position
I return the size
I print the elements
Array lists

I Array lists store data elements in an array


I A new array has to be created when elements are added or
removed and existing elements have to be copied into the new
array
public class ArrayListDouble {

p r i v a t e d o u b l e [ ] e l e m e n t s = new d o u b l e [ 0 ] ;

p u b l i c void i n s e r t ( i n t i , double x ) {
i f ( i < 0 | | i > this . size ()) {
throw new I n d e x O u t O f B o u n d s E x c e p t i o n ( ” I n d e x : ” + i ) ;
}
d o u b l e [ ] tmp = new d o u b l e [ t h i s . s i z e ( ) + 1 ] ;

f o r ( i n t j = 0 ; j < i ; j ++) {
tmp [ j ] = t h i s . e l e m e n t s [ j ] ;
}
tmp [ i ] = x ;
for ( int j = i ; j < this . size (); j ++) {
tmp [ j + 1 ] = t h i s . e l e m e n t s [ j ] ;
}
t h i s . e l e m e n t s = tmp ;
}

p u b l i c v o i d add ( d o u b l e x ) {
this . insert ( this . size () , x );
}

// o t h e r methods come h e r e ...


}
Demo Program
p u b l i c c l a s s ArrayListDoubleDemoProgram {

p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
A r r a y L i s t D o u b l e l i s t = new A r r a y L i s t D o u b l e ( ) ;

list . add ( 5 . 0 ) ;
list . add ( 4 . 0 ) ;
list . set (0 , 1 . 0 ) ;
list . print ();

l i s t . i n s e r t (1 , 3 . 0 ) ;
l i s t . print ();

l i s t . add ( 5 . 0 ) ;
l i s t . remove ( 2 ) ;
l i s t . print ();
}
}
Demo Program
p u b l i c c l a s s ArrayListDoubleDemoProgram {

p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
A r r a y L i s t D o u b l e l i s t = new A r r a y L i s t D o u b l e ( ) ;

list . add ( 5 . 0 ) ;
list . add ( 4 . 0 ) ;
list . set (0 , 1 . 0 ) ;
list . print ();

l i s t . i n s e r t (1 , 3 . 0 ) ;
l i s t . print ();

l i s t . add ( 5 . 0 ) ;
l i s t . remove ( 2 ) ;
l i s t . print ();
}
}

<1.0 , 4.0 >


<1.0 , 3 . 0 , 4.0 >
<1.0 , 3 . 0 , 5.0 >
Insert method
1 4 ArrayListDouble
elements

inside: insert(int i, double x) this


this ← list
inside main at: list.insert(1, 3.0); list
Insert method
1 4 ArrayListDouble
elements

inside: insert(int i, double x) this


this ← list
inside main at: list.insert(1, 3.0); list

1 4 ArrayListDouble
elements
1 3 4

inside: insert(int i, double x) tmp this


this ← list
inside main at: list.insert(1, 3.0); list
Insert method
1 4 ArrayListDouble
elements

inside: insert(int i, double x) this


this ← list
inside main at: list.insert(1, 3.0); list

1 4 ArrayListDouble
elements
1 3 4

inside: insert(int i, double x) tmp this


this ← list
inside main at: list.insert(1, 3.0); list

ArrayListDouble
elements
1 3 4

inside: insert(int i, double x) this


this ← list
inside main at: list.insert(1, 3.0); list
Linked lists . . .
Linked lists

I A linked list all elements as a sequence of nodes


I Each node stores
I the data element and
I a link to the next node

I Normally, a special head node is used


Doubly linked lists
I A doubly linked list is an extension of a (single) linked list
I In addition a node object stores the link to previous node

I The two links allow walking along the list in either direction
with equal ease.
I The previous node of the head is the last node of the list
I Normally, a special head node is used
Example: Polygon

A polygon is a closed path of line segments.


Example: Polygon

A polygon is defined by a list of points. The start point of the first


segment is at the same time the end point of the last segment.

P :=< p0 , p1 , ..., pn−1 >


Often data structures are used within another classes to store and
organize the attributes.
A polygon can be implemented as array list or linked list. The
choice depends on the type of usage:
I If you often need a direct access via an index - use array list
implementation.
I If you often modify the polygon via insert, remove or add
operations - use linked list implementation.
Example: Polygon

A polygon is defined by a list of points. The start point of the first


segment is at the same time the end point of the last segment.

P :=< p0 , p1 , ..., pn−1 >


Often data structures are used within another classes to store and
organize the attributes.
A polygon can be implemented as array list or linked list. The
choice depends on the type of usage:
I If you often need a direct access via an index - use array list
implementation.
I If you often modify the polygon via insert, remove or add
operations - use linked list implementation.
Here we will implement the polygon class as a linked list
Operations for polygons

I Add a point at the beginning of the list of points


I Find a node before a specified node
I Remove a specified node
I Draw the polygon on the screen
Polygon demo program
p u b l i c c l a s s PolygonDemoProgram {

p u b l i c s t a t i c v o i d main ( S t r i n g [ ] args ) {
V i e w e r v = new V i e w e r ( ) ;
P o l y g o n p = new P o l y g o n ( ) ;

p. addFirst (1.0 , 0.0);


p. addFirst (2.0 , 5.0);
p. addFirst (8.0 , 4.0);
p. addFirst (7.0 , 3.0);
p. print ();

PNode n = p . f i n d B e f o r e ( 8 . 0 , 4 . 0 ) ;

n . p r i n t ( ” Found : ” ) ;
System . o u t . p r i n t l n ( ) ;

p . remove ( 7 . 0 , 3 . 0 ) ;
p. print ();
p . draw ( v ) ;
v . s e t V i s i b l e ( true ) ;
}
}
Program output
Program output

− >(7.0 , 3 . 0 ) − > ( 8 . 0 , 4 . 0 ) − > ( 2 . 0 , 5 . 0 ) − > ( 1 . 0 , 0 . 0 )


Found : ( 7 . 0 , 3 . 0 )
− >(8.0 , 4 . 0 ) − > ( 2 . 0 , 5 . 0 ) − > ( 1 . 0 , 0 . 0 )
UML class diagram

Polygon PNode
- head: PNode - x: double
+ addFirst(x: double, y: double) - y: double
+ findBefore(x: double, y: double): PNode - next: PNode
+ remove(x: double, y: double): void + PNode(x: double, y: double, next: PNode)
+ draw(v: Viewer): void + setNext(next: PNode): void
+ print(): void + getNext(): PNode
+ getX(): double
+ getY(): double
+ print(l: String): void
UML class diagram

Polygon PNode
- head: PNode - x: double
+ addFirst(x: double, y: double) - y: double
+ findBefore(x: double, y: double): PNode - next: PNode
+ remove(x: double, y: double): void + PNode(x: double, y: double, next: PNode)
+ draw(v: Viewer): void + setNext(next: PNode): void
+ print(): void + getNext(): PNode
+ getX(): double
+ getY(): double
+ print(l: String): void

I Node class stores point position and pointer to next node


(implementation is straightforward, not discussed here)
I Polygon has pointer to head node
I Add first adds node at beginning of chain of nodes
I Find before returns the node before the specified node
I Remove removes specified node
Polygon objects
PNode
x=0
Polygon y=0
head next = null
head node

p inside main after: Polygon p = new Polygon();


Polygon objects
PNode
x=0
Polygon y=0
head next = null
head node

p inside main after: Polygon p = new Polygon();

PNode PNode PNode PNode PNode


x=0 x=7 x=8 x=2 x=1
Polygon y=0 y=3 y=4 y=5 y=0
head next next next next next = null
head node

p n inside main after: PNode n = p.findBefore(8.0, 4.0);


Polygon objects
PNode
x=0
Polygon y=0
head next = null
head node

p inside main after: Polygon p = new Polygon();

PNode PNode PNode PNode PNode


x=0 x=7 x=8 x=2 x=1
Polygon y=0 y=3 y=4 y=5 y=0
head next next next next next = null
head node

p n inside main after: PNode n = p.findBefore(8.0, 4.0);

PNode PNode PNode PNode PNode


x=0 x=7 x=8 x=2 x=1
Polygon y=0 y=3 y=4 y=5 y=0
head next next next next next = null
head node

p n inside main after: p.remove(7.0, 3.0);

I Advantage of using a head node for the empty list:


Every node has a predecessor
Implementation of Polygon class
Implementation of Polygon class

p u b l i c c l a s s Polygon {

p r i v a t e Node head = new Node ( 0 , 0 , n u l l ) ;

p u b l i c void a d d F i r s t ( double x , double y ) {


t h i s . head . s e t N e x t ( new Node ( x , y , t h i s . head . g e t N e x t ( ) ) ) ;
}

public void p r i n t () {
Node node = head . g e t N e x t ( ) ;

w h i l e ( node != n u l l ) {
node . p r i n t ( ”−>” ) ;
node = node . g e t N e x t ( ) ;
}
System . o u t . p r i n t l n ( ) ;
}

// o t h e r methods come h e r e ...


}
Other interesting methods
Find node before a specified node
Other interesting methods
Find node before a specified node
p u b l i c PNode f i n d B e f o r e ( d o u b l e x , d o u b l e y ) {
PNode n = t h i s . head ;

w h i l e ( n . g e t N e x t ( ) != n u l l ) {
i f ( n . g e t N e x t ( ) . getX ()==x && n . g e t N e x t ( ) . getY ()==y ) {
return n ;
}
n = n . getNext ( ) ;
}
return null ;
}
Other interesting methods
Find node before a specified node
p u b l i c PNode f i n d B e f o r e ( d o u b l e x , d o u b l e y ) {
PNode n = t h i s . head ;

w h i l e ( n . g e t N e x t ( ) != n u l l ) {
i f ( n . g e t N e x t ( ) . getX ()==x && n . g e t N e x t ( ) . getY ()==y ) {
return n ;
}
n = n . getNext ( ) ;
}
return null ;
}

Remove a node
Other interesting methods
Find node before a specified node
p u b l i c PNode f i n d B e f o r e ( d o u b l e x , d o u b l e y ) {
PNode n = t h i s . head ;

w h i l e ( n . g e t N e x t ( ) != n u l l ) {
i f ( n . g e t N e x t ( ) . getX ()==x && n . g e t N e x t ( ) . getY ()==y ) {
return n ;
}
n = n . getNext ( ) ;
}
return null ;
}

Remove a node
p u b l i c v o i d remove ( d o u b l e x , d o u b l e y ) {
PNode n = t h i s . f i n d B e f o r e ( x , y ) ;
PNode newNextNode = n . g e t N e x t ( ) . g e t N e x t ( ) ;

n . s e t N e x t ( newNextNode ) ;
}
Other interesting methods

Draw polygon
Other interesting methods

Draw polygon
p u b l i c v o i d draw ( V i e w e r v ) {
P o l y l i n e p o l y l i n e = new P o l y l i n e ( ) ;
PNode node = t h i s . head . g e t N e x t ( ) ;

w h i l e ( node != n u l l ) {
p o l y l i n e . a d d V e r t e x ( node . getX ( ) , node . getY ( ) , 0 , 0 ) ;
node = node . g e t N e x t ( ) ;
}
node = t h i s . head . g e t N e x t ( ) ;
p o l y l i n e . a d d V e r t e x ( node . getX ( ) , node . getY ( ) , 0 ) ;

p o l y l i n e . setColor (” black ” );
v . addObject3D ( p o l y l i n e ) ;
}
Trees . . .
Trees
I Trees describe hierarchical structures of elements based on a
set of linked nodes
I Each node in a tree stores an element and has zero or more
child nodes, which are below it in the tree
I The topmost node in a tree is called the root node
I Nodes at the bottommost level of the tree are called leaf
nodes
Types of trees
I Any node in a tree T, together with all the nodes below it,
comprise a so-called subtree of T
I Different tree types are distinguished by the number of
possible child nodes
I Binary trees
I Quad trees
I Oct trees
I Often trees are used to store elements in a certain order
Binary tree

I Often trees are used to store elements in a certain order


I For example the binary search tree
I The left subtree of a node contains only nodes which are less
than the node
I The right subtree of a node contains only nodes which are not
less than the node
I Both the left and right subtrees must also be binary search
trees

See exercise. . .
Excursus: Interfaces. . .
Interfaces by example

public interface ListOfDoubles {

p u b l i c void a d d F i r s t ( double x ) ;

public void p r i n t ( String l ) ;


}

I An interface defines operations without specifying how to


implement them
I Interfaces are the Java replacement for multiple inheritance
I An interface can be implemented by many classes
UML class diagram

ListOfDoubles
{interface}
+ addFirst(x: double): void
+ print(l: String): void

ArrayListOfDoubles LinkedListOfDoubles
- values: double[] - head: Node
+ addFirst(x: double): void + addFirst(x: double): void
+ print(l: String): void + print(l: String): void

I The interface is implemented by two classes:


I One using an array
I One using a linked list
I Implementing classes are connected to the interface by a
dashed line with a triangle pointing to the interface
I Implementing classes provide methods defined by the interface
Array list implementation
p u b l i c c l a s s A r r a y L i s t O f D o u b l e s implements L i s t O f D o u b l e s {

p r i v a t e double [ ] v a l u e s = new d o u b l e [ 0 ] ;

p u b l i c void a d d F i r s t ( double x ) {
int n = this . values . length ;
d o u b l e [ ] tmp = new d o u b l e [ n + 1 ] ;

tmp [ 0 ] = x ;
System . a r r a y c o p y ( t h i s . v a l u e s , 0 , tmp , 1 , n ) ;
t h i s . v a l u e s = tmp ;
}

public void p r i n t ( String l ) {


System . o u t . p r i n t ( l + ”<” ) ;
for ( int i = 0; i < this . values . length ; i ++) {
System . o u t . p r i n t ( t h i s . v a l u e s [ i ] ) ;
System . o u t . p r i n t ( ” ” ) ;
}
System . o u t . p r i n t l n ( ”>” ) ;
}
}
Array list implementation

p u b l i c c l a s s L i n k e d L i s t O f D o u b l e s implements L i s t O f D o u b l e s {

p r i v a t e Node head = new Node ( 0 , n u l l ) ;

p u b l i c void a d d F i r s t ( double x ) {
Node n = new Node ( x , t h i s . head . g e t N e x t ( ) ) ;
t h i s . head . s e t N e x t ( n ) ;
}

public void p r i n t ( String l ) {


Node n = t h i s . head . g e t N e x t ( ) ;

System . o u t . p r i n t ( l + ”<” ) ;
w h i l e ( n != n u l l ) {
System . o u t . p r i n t ( n . g e t V a l u e ( ) + ” ” ) ;
n = n . getNext ( ) ;
}
System . o u t . p r i n t l n ( ”>” ) ;
}
}
Demo program
p u b l i c c l a s s ListOfDoublesDemoProgram {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
L i s t O f D o u b l e s l 1 = new A r r a y L i s t O f D o u b l e s ( ) ;
L i s t O f D o u b l e s l 2 = new L i n k e d L i s t O f D o u b l e s ( ) ;

l1 . addFirst (1.1);
l1 . addFirst (6.2);
l1 . addFirst (9.4);
l2 . addFirst (1.1);
l2 . addFirst (6.2);
l2 . addFirst (9.4);
l1 . p r i n t ( ” l 1=” ) ;
l2 . p r i n t ( ” l 2=” ) ;
}
}
Demo program
p u b l i c c l a s s ListOfDoublesDemoProgram {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
L i s t O f D o u b l e s l 1 = new A r r a y L i s t O f D o u b l e s ( ) ;
L i s t O f D o u b l e s l 2 = new L i n k e d L i s t O f D o u b l e s ( ) ;

l1 . addFirst (1.1);
l1 . addFirst (6.2);
l1 . addFirst (9.4);
l2 . addFirst (1.1);
l2 . addFirst (6.2);
l2 . addFirst (9.4);
l1 . p r i n t ( ” l 1=” ) ;
l2 . p r i n t ( ” l 2=” ) ;
}
}

l 1 =<9.4 6 . 2 1 . 1 >
l 2 =<9.4 6 . 2 1 . 1 >
Demo program
p u b l i c c l a s s ListOfDoublesDemoProgram {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
L i s t O f D o u b l e s l 1 = new A r r a y L i s t O f D o u b l e s ( ) ;
L i s t O f D o u b l e s l 2 = new L i n k e d L i s t O f D o u b l e s ( ) ;

l1 . addFirst (1.1);
l1 . addFirst (6.2);
l1 . addFirst (9.4);
l2 . addFirst (1.1);
l2 . addFirst (6.2);
l2 . addFirst (9.4);
l1 . p r i n t ( ” l 1=” ) ;
l2 . p r i n t ( ” l 2=” ) ;
}
}

l 1 =<9.4 6 . 2 1 . 1 >
l 2 =<9.4 6 . 2 1 . 1 >

I Both implementations give the same result


I The interface is used as data type
Java Collections Framework

I Any serious programming projects requires efficient and


reliable classes providing data structures to store collections of
objects.
I Java provides such classes in the so called Java Collections
Framework.
I An excellent comprehensive introduction is given under
http://java.sun.com/docs/books/tutorial/collections
I The framework makes a distinction between:
I Interfaces defining available operations
I Classes implementing the interfaces in different ways
(ArrayList vs. LinkedList)
Core interfaces and classes
E
E Collection
Iterable {interface}
{interface} + add(e: E): boolean
+ iterator(): Iterator<E> + size(): int
+ contains(o: Object): boolean
... E
Queue
{interface}
+ poll(): E
E E ...
List Set
{interface} {interface}
+ set(idx: int, e: E): E ... E
+ get(idx: int): E HashSet
... ...
...
E
SortedSet
E E {interface} E
ArrayList LinkedList + first(): E TreeSet
... ... + last(): E ...
... ... ... ...

E: The data type, the interface is used for


Iteratable: Lets us use foreach loop
List: Store elements in an ordered sequence
Set: Store elements without duplicates
List demo program
L i s t <Double> l 1 = new A r r a y L i s t <Double > ( ) ;
L i s t <S t r i n g > l 2 = new L i n k e d L i s t <S t r i n g > ( ) ;

l1 . add ( 1 . 0 ) ;
l1 . add ( P I ) ;
l1 . add ( 1 . 0 ) ;
l2 . add ( ” B e e t h o v e n ” ) ;
l2 . add ( ” S t r a w i n s k y ” ) ;
l2 . add ( ” Bach ” ) ;
l2 . add ( ” B e e t h o v e n ” ) ;

System . o u t . p r i n t ( ” Numbers : ” ) ;
f o r ( double d : l 1 ) {
System . o u t . p r i n t ( d + ” ” ) ;
}
System . o u t . p r i n t ( ” \ nComposers : ” ) ;
for ( String s : l2 ) {
System . o u t . p r i n t ( s + ” ” ) ;
}
List demo program
L i s t <Double> l 1 = new A r r a y L i s t <Double > ( ) ;
L i s t <S t r i n g > l 2 = new L i n k e d L i s t <S t r i n g > ( ) ;

l1 . add ( 1 . 0 ) ;
l1 . add ( P I ) ;
l1 . add ( 1 . 0 ) ;
l2 . add ( ” B e e t h o v e n ” ) ;
l2 . add ( ” S t r a w i n s k y ” ) ;
l2 . add ( ” Bach ” ) ;
l2 . add ( ” B e e t h o v e n ” ) ;

System . o u t . p r i n t ( ” Numbers : ” ) ;
f o r ( double d : l 1 ) {
System . o u t . p r i n t ( d + ” ” ) ;
}
System . o u t . p r i n t ( ” \ nComposers : ” ) ;
for ( String s : l2 ) {
System . o u t . p r i n t ( s + ” ” ) ;
}

Numbers : 1 . 0 3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 1 . 0
Composers : B e e t h o v e n S t r a w i n s k y Bach B e e t h o v e n
Set demo program
Set<Double> l 1 = new HashSet<Double > ( ) ;
Set<S t r i n g > l 2 = new T r e e S e t <S t r i n g > ( ) ;

l1 . add ( 1 . 0 ) ;
l1 . add ( P I ) ;
l1 . add ( 1 . 0 ) ;
l2 . add ( ” B e e t h o v e n ” ) ;
l2 . add ( ” S t r a w i n s k y ” ) ;
l2 . add ( ” Bach ” ) ;
l2 . add ( ” B e e t h o v e n ” ) ;

System . o u t . p r i n t ( ” Numbers : ” ) ;
f o r ( double d : l 1 ) {
System . o u t . p r i n t ( d + ” ” ) ;
}
System . o u t . p r i n t ( ” \ nComposers : ” ) ;
for ( String s : l2 ) {
System . o u t . p r i n t ( s + ” ” ) ;
}
Set demo program
Set<Double> l 1 = new HashSet<Double > ( ) ;
Set<S t r i n g > l 2 = new T r e e S e t <S t r i n g > ( ) ;

l1 . add ( 1 . 0 ) ;
l1 . add ( P I ) ;
l1 . add ( 1 . 0 ) ;
l2 . add ( ” B e e t h o v e n ” ) ;
l2 . add ( ” S t r a w i n s k y ” ) ;
l2 . add ( ” Bach ” ) ;
l2 . add ( ” B e e t h o v e n ” ) ;

System . o u t . p r i n t ( ” Numbers : ” ) ;
f o r ( double d : l 1 ) {
System . o u t . p r i n t ( d + ” ” ) ;
}
System . o u t . p r i n t ( ” \ nComposers : ” ) ;
for ( String s : l2 ) {
System . o u t . p r i n t ( s + ” ” ) ;
}

Numbers : 3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 1 . 0
Composers : Bach B e e t h o v e n S t r a w i n s k y
Summary

I Specify type of data to be stored in sharp brackets


I For primitive types, use the corresponding wrapper type
I Use foreach loop to process all elements efficiently
Maps

K,V
Map
{interface}
+ put(key: K, value: V): V K,V
+ get(key: K): V HashMap
+ keySet(): Set<K> ...
+ size(): int ...
...

K,V K,V
SortedMap TreeMap
{interface} ...
... ...

I Maps store key value pairs


I Uses: Dictionary, Phone book, . . .
I A sorted map is sorted by the keys
Map<C h a r a c t e r , I n t e g e r > cm = new HashMap<C h a r a c t e r , I n t e g e r > ( ) ;
cm . p u t ( ’ a ’ , 9 9 ) ;
cm . p u t ( ’ b ’ , 1 ) ;
cm . p u t ( ’ c ’ , 6 ) ;
cm . p u t ( ’ d ’ , 8 5 ) ;

f o r ( c h a r k e y : cm . k e y S e t ( ) ) {
System . o u t . p r i n t ( k e y + ”−>” + cm . g e t ( k e y ) + ” ” ) ;
}
Map<C h a r a c t e r , I n t e g e r > cm = new HashMap<C h a r a c t e r , I n t e g e r > ( ) ;
cm . p u t ( ’ a ’ , 9 9 ) ;
cm . p u t ( ’ b ’ , 1 ) ;
cm . p u t ( ’ c ’ , 6 ) ;
cm . p u t ( ’ d ’ , 8 5 ) ;

f o r ( c h a r k e y : cm . k e y S e t ( ) ) {
System . o u t . p r i n t ( k e y + ”−>” + cm . g e t ( k e y ) + ” ” ) ;
}

d−>85 b−>1 c−>6 a−>99


Map<C h a r a c t e r , I n t e g e r > cm = new HashMap<C h a r a c t e r , I n t e g e r > ( ) ;
cm . p u t ( ’ a ’ , 9 9 ) ;
cm . p u t ( ’ b ’ , 1 ) ;
cm . p u t ( ’ c ’ , 6 ) ;
cm . p u t ( ’ d ’ , 8 5 ) ;

f o r ( c h a r k e y : cm . k e y S e t ( ) ) {
System . o u t . p r i n t ( k e y + ”−>” + cm . g e t ( k e y ) + ” ” ) ;
}

d−>85 b−>1 c−>6 a−>99

Map<C h a r a c t e r , I n t e g e r > cm = new TreeMap<C h a r a c t e r , I n t e g e r > ( ) ;


cm . p u t ( ’ a ’ , 9 9 ) ;
cm . p u t ( ’ b ’ , 1 ) ;
cm . p u t ( ’ c ’ , 6 ) ;
cm . p u t ( ’ d ’ , 8 5 ) ;

f o r ( c h a r k e y : cm . k e y S e t ( ) ) {
System . o u t . p r i n t ( k e y + ”−>” + cm . g e t ( k e y ) + ” ” ) ;
}
Map<C h a r a c t e r , I n t e g e r > cm = new HashMap<C h a r a c t e r , I n t e g e r > ( ) ;
cm . p u t ( ’ a ’ , 9 9 ) ;
cm . p u t ( ’ b ’ , 1 ) ;
cm . p u t ( ’ c ’ , 6 ) ;
cm . p u t ( ’ d ’ , 8 5 ) ;

f o r ( c h a r k e y : cm . k e y S e t ( ) ) {
System . o u t . p r i n t ( k e y + ”−>” + cm . g e t ( k e y ) + ” ” ) ;
}

d−>85 b−>1 c−>6 a−>99

Map<C h a r a c t e r , I n t e g e r > cm = new TreeMap<C h a r a c t e r , I n t e g e r > ( ) ;


cm . p u t ( ’ a ’ , 9 9 ) ;
cm . p u t ( ’ b ’ , 1 ) ;
cm . p u t ( ’ c ’ , 6 ) ;
cm . p u t ( ’ d ’ , 8 5 ) ;

f o r ( c h a r k e y : cm . k e y S e t ( ) ) {
System . o u t . p r i n t ( k e y + ”−>” + cm . g e t ( k e y ) + ” ” ) ;
}

a−>99 b−>1 c−>6 d−>85


Complexity of operations
The choice of a certain implementation depends on the desired
properties of the collection and the type of usage.
Complexity of operations
The choice of a certain implementation depends on the desired
properties of the collection and the type of usage.

Complexity of operations

Implementation add/put get sorted


ArrayList O(n) O(1) yes
LinkedList O(1) O(n) yes
TreeSet O(log(n)) O(log(n)) yes
HashSet O(1) O(1) no
TreeMap O(log(n)) O(log(n)) yes
HashMap O(1) O(1) no
Complexity of operations
The choice of a certain implementation depends on the desired
properties of the collection and the type of usage.

Complexity of operations

Implementation add/put get sorted


ArrayList O(n) O(1) yes
LinkedList O(1) O(n) yes
TreeSet O(log(n)) O(log(n)) yes
HashSet O(1) O(1) no
TreeMap O(log(n)) O(log(n)) yes
HashMap O(1) O(1) no

Hash sets and maps are based on hashing functions. A hashing


function maps an object on an integer such that this integer can
be used as index for storage in an array.
Application example: Book analyzer. . .
Count appearances of persons in a book
How often do the names
I Mulligan
I Molly
I Bloom
I Dedalus
appear in the book Ulysses by
James Joyce
Count appearances of persons in a book
How often do the names
I Mulligan
I Molly
I Bloom
I Dedalus
appear in the book Ulysses by
James Joyce
Solution ingredients
Gutenberg project: Free books on the web (www.gutenberg.org)
URL: Class to read from a webserver
Scanner: Class to tokenize a stream
Set: List of persons to consider
Map: Count occurences
Demo program

String url =
” h t t p : / /www . g u t e n b e r g . o r g / f i l e s /4300/4300 −8. t x t ” ;
Book b = new Book ( u r l ) ;

b. addImportantPerson (” Mulligan ” ) ;
b. addImportantPerson ( ” Molly ” ) ;
b. a d d I m p o r t a n t P e r s o n ( ” Bloom ” ) ;
b. addImportantPerson ( ” Dedalus ” ) ;
b. listAppearances ();
Demo program

String url =
” h t t p : / /www . g u t e n b e r g . o r g / f i l e s /4300/4300 −8. t x t ” ;
Book b = new Book ( u r l ) ;

b. addImportantPerson (” Mulligan ” ) ;
b. addImportantPerson ( ” Molly ” ) ;
b. a d d I m p o r t a n t P e r s o n ( ” Bloom ” ) ;
b. addImportantPerson ( ” Dedalus ” ) ;
b. listAppearances ();

M u l l i g a n : 115
M o l l y : 41
D e d a l u s : 116
Bloom : 428
Basic methods

p u b l i c c l a s s Book {

p r i v a t e URL u r l ;
p r i v a t e Set<S t r i n g > p e r s o n s = new HashSet<S t r i n g > ( ) ;

p u b l i c Book ( S t r i n g u r l ) t h r o w s I O E x c e p t i o n {
t h i s . u r l = new URL( u r l ) ;
}

public void addImportantPerson ( String p) {


t h i s . p e r s o n s . add ( p ) ;
}

// o t h e r methods come h e r e . . .
}
List persons
p u b l i c void l i s t A p p e a r a n c e s ( ) throws IOException {
S c a n n e r s c a n n e r = new S c a n n e r ( t h i s . u r l . o p e n S t r e a m ( ) ) ;
Map<S t r i n g , I n t e g e r > a p p e a r a n c e s
= new TreeMap<S t r i n g , I n t e g e r > ( ) ;

for ( String p : this . persons ) {


appearances . put ( p , 0 ) ;
}

while ( scanner . hasNext ( ) ) {


String s = scanner . next ( ) ;

i f ( this . persons . contains ( s )) {


System . o u t . p r i n t l n ( ” Found : ” + s ) ;
appearances . put ( s , appearances . get ( s ) + 1 ) ;
}
}

for ( String person : appearances . keySet ( ) ) {


System . o u t . p r i n t l n ( p e r s o n + ” : ”
+ appearances . get ( person ) ) ;
}
}
Quadtrees . . .
Quadtrees

Domain with properties

Statement of problem
Given: A domain where each point of the domain is
associated with a certain property, e.g. the color.
Quadtrees

Domain with properties Partitioning of domain

Statement of problem
Given: A domain where each point of the domain is
associated with a certain property, e.g. the color.
Needed: A partitioning of the domain into simple, rectangular
subdomains having mostly uniform properties.
Quadtrees
1 2
1 2 3 4
3 4
1 2 3 4

1 2 3 4

1 2 3 4 1 2 3 4
Domain with properties Partitioning of domain Corresponding quadtree

Statement of problem
Given: A domain where each point of the domain is
associated with a certain property, e.g. the color.
Needed: A partitioning of the domain into simple, rectangular
subdomains having mostly uniform properties.
Solution idea
I Recursively refine region where needed
I Store rectangles in a tree-like data structure
I Each node in the tree represents one rectangle
I A tree node can have either zero or four subnodes
Applications of quadtrees

Quadtrees are widely used in various fields of computer graphics,


engineering and information systems:
I Grid generation for finite element meshes
I Collision detection
I Geoinformation systems: Store data efficiently
I Image analysis
Java implementation. . .
Domain class
Domain
- image: BufferedImage
- colors: int[]
+ Domain(filename: String, nColors: int)
+ colorIdxAt(x: double, y: double): int
+ isMonochromatic(x: double, y: double, s: double): boolean

I Define domain using an image file (.jpg, .png, . . . )


I The domain is of size 1 × 1
I For the image, nColors different colors are distinguished
I The colorIdxAt returns the index of the color at the
specified position
I isMonochromatic tests if the specified region contains only
colors of one index

1 2 3 4 5
Domain class in Java

p u b l i c c l a s s Domain {

private static i n t N SAMPLES = 2 5 ;

private int [ ] colors ;


p r i v a t e B u f f e r e d I m a g e image ;

p u b l i c Domain ( S t r i n g f i l e n a m e , i n t n C o l o r s )
throws IOException {
d o u b l e dc = 2 5 5 . 0 / n C o l o r s ;

t h i s . image = ImageIO . r e a d ( new F i l e ( f i l e n a m e ) ) ;


t h i s . c o l o r s = new i n t [ n C o l o r s ] ;
f o r ( i n t i = 0 ; i < n C o l o r s ; i ++) {
t h i s . c o l o r s [ i ] = ( i n t ) ( ( i + 1 ) ∗ dc ) ;
}
}

// o t h e r methods go h e r e ...
}
Getting the color index
p u b l i c i n t c o l o r I d x A t ( double x , double y ) {
i n t iw = t h i s . image . g e t W i d t h ( n u l l ) ;
i n t i h = t h i s . image . g e t H e i g h t ( n u l l ) ;
i n t px = ( i n t ) ( x ∗ iw ) ;
i n t py = ( i n t ) ( i h − y ∗ i h ) ;
C o l o r c = new C o l o r ( t h i s . image . getRGB ( px , py ) ) ;
i n t b = ( c . getRed ( ) + c . getGreen ( ) + c . g e t B l u e ( ) ) / 3 ;
int idx = Arrays . binarySearch ( this . colors , b ) ;

i f ( i d x >= 0 ) {
return idx ;
} else {
r e t u r n −i d x − 1 ;
}
}

I Parameters x and y are in [0, 1]


I Map standard domain [0, 1]2 on pixel domain of picture
I Use average color intensity (grayscale image)
I Search color index using binary search
Finding out if a subdomain is monochromatic
p u b l i c boolean isMonochromatic ( double x ,
double y , double s ) {
d o u b l e d = s / N SAMPLES ;
int idx = colorIdxAt (x + d / 2 , y + d / 2);

for ( int i = 0; i < N SAMPLES ; i ++) {


d o u b l e px = x + ( i + 0.5) ∗ d ;
for ( int j = 0; j < N SAMPLES ; j ++) {
d o u b l e py = y + ( j + 0.5) ∗ d ;

i f ( i d x != t h i s . c o l o r I d x A t ( px , py ) ) {
return false ;
}
}
}
return true ;
}

I Parameters x, y and s specify subdomain S ⊆ [0, 1]2


I Check color index at sample points against reference color
I Return false if color index does not match
Using the Domain class
Domain d = new Domain ( ” img / s e c t i o n 1 . png ” , 1 0 ) ;

System . o u t . p r i n t l n ( ” (0.1 , 0.1): ”


+ d . colorIdxAt (0.1 , 0.1));
System . o u t . p r i n t l n ( ” (0.1 , 0.9): ”
+ d . colorIdxAt (0.1 , 0.9));
System . o u t . p r i n t l n ( ” (0.8 , 0.2): ”
+ d . colorIdxAt (0.8 , 0.2));
System . o u t . p r i n t l n ( ” ( 0 . 1 , 0 . 1 , 0 . 1 ) : ”
+ d . isMonochromatic (0.1 , 0.1 , 0 . 1 ) ) ;
System . o u t . p r i n t l n ( ” ( 0 . 0 , 0 . 0 , 1 . 0 ) : ”
+ d . isMonochromatic (0.0 , 0.0 , 1 . 0 ) ) ;
System . o u t . p r i n t l n ( ” ( 0 . 3 , 0 . 3 , 0 . 4 ) : ”
+ d . isMonochromatic (0.3 , 0.3 , 0 . 4 ) ) ;

(0.1 , 0.1): 4
(0.1 , 0.9): 6
(0.8 , 0.2): 3
(0.1 , 0.1 , 0.1): true
(0.0 , 0.0 , 1.0): false
(0.3 , 0.3 , 0.4): false
The QuadTree class

QuadTree
- root: QuadTreeNode
+ QuadTree(d: Domain, depth: int)
+ draw(ov: boolean, cm: int, v: Viewer): void

QuadTree class
I Pointer to root node
I Specify domain and refinement depth in constructor
I Draw quadtree, parameters determine appearance
The QuadTreeNode class

QuadTreeNode
- colorIdx: int
- nodes: QuadTreeNode[]
- size: double
- x: double
- y: double
+ QuadTreeNode(d: Domain, x: double, y: double, size: double)
+ draw(ps: PolygonSet): void
+ refine(d: Domain, depth: int): void
- isLeaf(): boolean

QuadTreeNode class
I Specify domain, position and size in constructor
I Draw using a PolygonSet
I Refine up to the specified level
I Check if the node is a leaf not (i.e. does not have subnodes)
QuadTree in Java

p u b l i c c l a s s QuadTree {

p r i v a t e QuadTreeNode r o o t ;

p u b l i c QuadTree ( Domain d , i n t d e p t h ) {
t h i s . r o o t = new QuadTreeNode ( d , 0 . 0 , 0 . 0 , 1 . 0 ) ;
t h i s . r oot . r e f i n e (d , depth ) ;
}

p u b l i c v o i d draw ( b o o l e a n ov , i n t cm , V i e w e r v ) {
P o l y g o n S e t p s = new P o l y g o n S e t ( ) ;

t h i s . r o o t . draw ( p s ) ;
ps . s e t C o l o r i n g B y D a t a ( t r u e ) ;
p s . s e t O u t l i n e s V i s i b l e ( ov ) ;
p s . s e t C o l o r M o d e (cm ) ;
ps . c r e a t e C o l o r s ( ) ;
v . addObject3D ( p s ) ;
}
}
QuadTreeNode in Java
p u b l i c c l a s s QuadTreeNode {

private int colorIdx ;


private QuadTreeNode [ ] n o d e s ;
private double s i z e ;
private double x ;
private double y ;

p u b l i c QuadTreeNode ( Domain d , d o u b l e x , d o u b l e y ,
double s i z e ) {
double s2 = s i z e / 2 ;
t h i s . c o l o r I d x = d . c o l o r I d x A t ( x + s2 , y + s 2 ) ;
this . x = x ;
this . y = y ;
this . size = size ;
}

p r i v a t e boolean i s L e a f () {
r e t u r n t h i s . n o d e s == n u l l ;
}

// o t h e r methods go h e r e ...
}
Refinement procedure

The refine method can be implemented using this algorithm:

If the subdomain represented by this QuadTreeNode is not


monochromatic:
1. Create the array for the four subtree nodes
2. For i = 0, 1 and j = 0, 1
2.1 Create a new QuadTreeNode at the right position and of the
right size
2.2 Refine the new node if depth is larger than zero. Pass
depth-1 as parameter
2.3 Store the new node in the array of subtree nodes
Drawing a node

The draw method can be implemented as follows:

If the node is a leaf node


1. add a polygon to the specified polygon set
otherwise
1. invoke the draw method for all subnodes
Example 1
Example 2

You might also like