data structures a data structure is a collection of data organized in some fashion that permits...

26
Data Structures • A data structure is a collection of data organized in some fashion that permits access to individual elements stored in the structure • This describes an Object but when we talk about a Collection, we are referring to a group of Objects – an array is one form of data structure that you are already familiar with but you, as a programmer, have to implement the methods to manipulate the array – an ArrayList is another form which is more appropriate because the ArrayList comes with already implemented methods to operate on the data structure • Java has many built in data structures known collectively as the Java Collections Framework (JCF) – many of which we will study in this and the next chapter – we will also consider how to implement a couple of these

Upload: reilly-fanning

Post on 14-Dec-2015

213 views

Category:

Documents


0 download

TRANSCRIPT

Data Structures• A data structure is a collection of data organized in some

fashion that permits access to individual elements stored in the structure

• This describes an Object but when we talk about a Collection, we are referring to a group of Objects– an array is one form of data structure that you are already familiar

with but you, as a programmer, have to implement the methods to manipulate the array

– an ArrayList is another form which is more appropriate because the ArrayList comes with already implemented methods to operate on the data structure

• Java has many built in data structures known collectively as the Java Collections Framework (JCF)– many of which we will study in this and the next chapter– we will also consider how to implement a couple of these

Abstract Data Types• An ADT is a data structure combined with– the methods (or functions/procedures) that can manipulate the data

structure (encapsulation)– while maintaining information hiding on the data structure itself to

prevent user programs from directly manipulating the data structure

• The concept of the ADT predates OOP but OOP includes both encapsulation and information hiding so we don’t need to study ADTs separately– OOP also includes inheritance and polymorphism so OOP is more

powerful than ADTs

• For chapters 22-23, we will look at ADTs (the data structures and necessary methods) and then see how to use the JCFs which implement them– we will also implement some ADTs from scratch to gain a better

understanding of ADTs

Collection Types• A Collection is a type that stores multiple individual

elements • In Java, the Collection class is an interface– The subtypes of the Collection interface are themselves

interfaces which have as children other abstract classes which have concrete child classes

• There are three subclasses of Collection:– List – ordered list of items (“ordered” does not mean numerical

or alphabetical order, but the order that the items were added)– Queue – list which stores items in a first-in first-out manner

• we restrict where we can add and remove items – always add at the end (rear) of the queue, always remove from the front

– Set – list which does not permit duplicate entries• all of these classes are defined in java.util

The Collection Class Subhierarchy

Set

SortedSet

AbstractSet

Collection

TreeSet

HashSet

List AbstractList

AbstractSequentialList

ArrayList

LinkedList

AbstractCollection

Vector Stack

LinkedHashSet

Interfaces Abstract Classes Concrete Classes

Queue AbstractQueue

Deque

PriorityQueue

We have already viewed the ArrayList, notice its placement under List, another optionis known as the LinkedList – we will explore linked structures separately

Notice that a Stack is a concrete class while a Queue is not

Collection as an Interface• Aside from the data structure, Collection defines (but does not

implement) methods for the following operations– add – add an item to the Collection

• each subtype of Collection may specify where an item is to be added

– addAll – take all elements of one Collection and add them to this Collection (this is like doing a set union operation)

– remove – remove the specified item from the Collection– removeAll – remove all elements of one Collection from this

Collection (this is like doing a set difference operation)– retainAll – compare this Collection to another and retain only those

elements that are found in the both Collections (like a set intersection operation)

• While these operations all operate on the Collection data structure itself, they are also boolean operations returning true if the collection is changed and false otherwise– clear – like removeAll but is a void method

«interface» java.util.Collection<E>

+add(o: E): boolean

+addAll(c: Collection<? extends E>): boolean

+clear(): void

+contains(o: Object): boolean

+containsAll(c: Collection<?>):boolean

+equals(o: Object): boolean

+hashCode(): int

+isEmpty(): boolean

+remove(o: Object): boolean

+removeAll(c: Collection<?>): boolean

+retainAll(c: Collection<?>): boolean

+size(): int

+toArray(): Object[]

Adds a new element o to this collection.

Adds all the elements in the collection c to this collection.

Removes all the elements from this collection.

Returns true if this collection contains the element o.

Returns true if this collection contains all the elements in c.

Returns true if this collection is equal to another collection o.

Returns the hash code for this collection.

Returns true if this collection contains no elements.

Removes the element o from this collection.

Removes all the elements in c from this collection.

Retains the elements that are both in c and in this collection.

Returns the number of elements in this collection.

Returns an array of Object for the elements in this collection.

«interface»

java.util.Iterator<E>

+hasNext(): boolean

+next(): E

+remove(): void

Returns true if this iterator has more elements to traverse.

Returns the next element from this iterator.

Removes the last element obtained using the next method.

«interface» java.lang.Iterable<E>

+iterator(): Iterator<E>

Returns an iterator for the elements in this collection.

The fullCollectioninterface

Notice thatCollectionitself implements Iterable sothat Collectionscan use theiterator forLoop

Other methodsnot mentionedon the previous slide

More on Collection• All of the Collection classes are generic in that you specify the

type as in – Queue<Integer> q=new Queue<>( );– Stack<String> s=new Stack<>( );

• The toArray method of Collection returns an array of the appropriate type containing all of the items in the Collection (e.g., an array of Integer for q)

• All subclasses of Collection except PriorityQueue have the clone method– they also all implement the interface Serializable

• One child of Collection is AbstractCollection which implements all of the abstract methods of Collection except for size and iterator– the concrete classes under Collection are TreeSet, HashSet,

LinkedHashSet, Vector, Stack, ArrayList, LinkedList and Priority Queue

Iterator Interface• To implement Iterable we have to implement the

following methods– next( ) – retrieve next sequential item– hasNext( ) – boolean– remove( ) – to remove the most recent item returned by

next( ) (a void method)

• By implementing Iterable on Collection classes, we can use the for-each (the iterator for loop) on any Collection

• The implementation of each of these methods depends in part on the implementation of the data structure used for the Collection– the actual implementation of Iterable will differ based on

whether the Collection is implemented using an array or a linked structure

Ways to Access a Collection• There are several ways we could access the elements of a

Collection given methods like get and the fact that these classes implement Iterable– Assume we have implemented one of the Collection classes as

variable a which is a collection of Integers• ArrayList<Integer> a

– Here we see 3 possible implementations: using a for-each loop, using a for loop using get(index), and using an Iterator

for(Integer temp:a) System.out.println(temp.intValue());

for(int i=0;i<a.size();i++) System.out.println(a.get(i));

Iterator<Integer> it=a.iterator();while(it.hasNext()) System.out.println(it.next().intValue());

The List Type• A List is an ADT that stores elements in a sequential order

– usually sequential means in the order inserted, but as we will see, various subclasses implement ordering in different ways

• Types of ordering include– ordered list – insert in the appropriate place to maintain numeric or

alphabetical order, remove based on item or index• there is no specific JCF to implement an ordered list, we will implement

one ourselves, the type to be stored needs to be Comparable

– unordered list – insert at one end of structure (could be front or rear end of structure), remove based on item or index

– stack – insert at the front of the structure, remove from front– queue – insert at the rear of the structure, remove from front– priority queue – insert in the appropriate place to maintain a

numeric (or possibly alphabetical) order using the item’s priority (usually numeric where the smaller the number, the higher the priority), always remove from front (highest priority item)

List Interface• The List Interface has additional methods to

– get the index of an item, traverse the list (move on to the next item), determine if the list is empty or full, return the size of the list, destroy the list and create a new list

• The JCF List Interface extends Collection– while List implements the methods of Collection, it also adds methods to

add at a specified index, retrieve the index of a specified item and remove the item of a specified index

• Two subtypes of List are ArrayList and LinkedList– these two types tell us the mechanism by which the list is stored – an

array or a linked list– these two types also dictate how the methods will be implemented– the LinkedList class also adds methods of adding, accessing and deleting

at the beginning or end of the List

• We will study the array vs linked implementations in the next unit where we compare their efficiencies

«interface» java.util.List<E>

+add(index: int, element:E): boolean

+addAll(index: int, c: Collection<? extends E>) : boolean

+get(index: int): E

+indexOf(element: Object): int

+lastIndexOf(element: Object): int

+listIterator(): ListIterator<E>

+listIterator(startIndex: int): ListIterator<E>

+remove(index: int): E

+set(index: int, element: E): E

+subList(fromIndex: int, toIndex: int): List<E>

«interface» java.util.Collection<E>

Adds a new element at the specified index.

Adds all the elements in c to this list at the specified index.

Returns the element in this list at the specified index.

Returns the index of the first matching element.

Returns the index of the last matching element.

Returns the list iterator for the elements in this list.

Returns the iterator for the elements from startIndex.

Removes the element at the specified index.

Sets the element at the specified index.

Returns a sublist from fromIndex to toIndex.

Creating a List From Another List• Once we have a List of one type, we can create a List of the

other type from the original list– Either by passing the original List in the constructor to the new List– Or by using the addAll method of Collection

ArrayList<Integer> a=new ArrayList<>();for(int i=0;i<10;i++)

a.add(i);LinkedList<Integer> l=new LinkedList<>(a);------------------------------------------a=new ArrayList<>(l);------------------------------------------a=new ArrayList<>();a.addAll(l);------------------------------------------l=new LinkedList<>();l.addAll(a);

We have ArrayList a withvalues, now create LinkedList l from a viathe constructor

Or create a new ArrayLista from l via the constructor

Or use addAll

Comparator Interface• Similar to Comparable

– Comparable requires implementing compareTo

• Comparator requires implementing equals and compare– public int compare(Object e1, Object e2) {…}

• returns negative int if e1 < e2, positive int if e1 > e2, 0 if e1 is equal to e2• Notice how this differs from compareTo which receives a single Object e

and compares this Object to e

– public boolean equals(Object e) {… }• returns true if e has the same values as this Object (that is, if this Object and

e would have compare return 0)

• You could implement both interfaces of Comparable and Comparator if desired as you can easily implement Comparable’s compareTo method if you have implemented Comparator

• public void compareTo(Object e) {return compare(this, e);}

Implementing Comparatorpublic class CompItem implements Comparator<CompItem> { private String first, middle, last; public Comp(String f, String m, String l){

first=f;middle=m;last=l; } public String getFirst() {return first;} public String getMid() {return middle;} public String getLast() {return last;} public boolean equals(ComparableItem i) {

if(compare(i,this)==0) return true; else return false; } public int compare(ComparableItem i1, ComparableItem i2) { if(i1.getLast().compareTo(i2.getLast())>0) return 1; else if(i1.getLast().compareTo(i2.getLast())<0) return -1; else if(i1.getFirst().compareTo(i2.getFirst())>0) return 1; else if(i1.getFirst().compareTo(i2.getFirst())<0) return -1; else if(i1.getMid().compareTo(i2.getMid())>0) return 1; else if(i1.getMid().compareTo(i2.getMid())<0) return -1;

else return 0; }}

Collections Class• We saw a Collection class earlier, what is a Collections class?• This class contains static methods to perform operations on

individual Collection objects

java.util.Collections +sort(list: List): void

+sort(list: List, c: Comparator): void

+binarySearch(list: List, key: Object): int

+binarySearch(list: List, key: Object, c: Comparator): int

+reverse(list: List): void

+reverseOrder(): Comparator

+shuffle(list: List): void

+shuffle(list: List): void

+copy(des: List, src: List): void

+nCopies(n: int, o: Object): List

+fill(list: List, o: Object): void

+max(c: Collection): Object

+max(c: Collection, c: Comparator): Object

+min(c: Collection): Object

+min(c: Collection, c: Comparator): Object

+disjoint(c1: Collection, c2: Collection): boolean

+frequency(c: Collection, o: Object): int

Sorts the specified list.

Sorts the specified list with the comparator.

Searches the key in the sorted list using binary search.

Searches the key in the sorted list using binary search with the comparator.

Reverses the specified list.

Returns a comparator with the reverse ordering.

Shuffles the specified list randomly.

Shuffles the specified list with a random object.

Copies from the source list to the destination list.

Returns a list consisting of n copies of the object.

Fills the list with the object.

Returns the max object in the collection.

Returns the max object using the comparator.

Returns the min object in the collection.

Returns the min object using the comparator.

Returns true if c1 and c2 have no elements in common.

Returns the number of occurrences of the specified element in the collection.

List

Collection

Methods to sort and binary search a Collection, reverse the elements in a Collection andobtain the minand max values

Thus the Collectionsclass deals witha Comparable Collection

Using Collections• Typically we will not create a Collections object but

instead pass messages directly to the Collections class

ArrayList<Integer> ints=new ArrayList<>();Random g=new Random();for(int i=0;i<100;i++) // create list of 100 random ints ints.add(new Integer(g.nextInt(1000)));for(int i=0;i<100;i++) // print them System.out.println(ints.get(i));Collections.sort(ints); // sort the listSystem.out.println("--------------------");for(int i=0;i<100;i++) // print sorted version System.out.println(ints.get(i));

Alternatively, we can specify a different form of sort:

Collections.sort(ints, Collections.reverseOrder());

Another Example• How many times might a number repeated in a

randomly generated list? Let’s generate 100 ints from 0-999 and see

• We can also sort the list and then, while iterating through the sorted list see if adjacent values are the same and output them, but this is easier

ArrayList<Integer> ints=new ArrayList<>();int temp;Random g=new Random();for(int i=0;i<100;i++) ints.add(new Integer(g.nextInt(1000)));for(int i=0;i<1000;i++) { temp=Collections.frequency(ints,new Integer(i)); if(temp>1)

System.out.println(i + " occurs " + temp + " times");}

Vector and Stack Classes• The Vector class is a child of AbstractList and a

sibling of ArrayList– How does Vector differ from ArrayList? – It is the same except that Vector contains synchronized

methods for accessing and modifying elements of the vector• synchronization is used to implement threads so that multiple

different Objects can modify the one structure at the same time such that modifications do not cause data corruption

• we look at this idea in several future classes like 362, 402 and 460 so we will skip the topic here

• The Stack class is a child of Vector but implements only methods to access the data structure at one end – the top via push, pop, peek operations

java.util.Stack<E>

+Stack()

+empty(): boolean

+peek(): E

+pop(): E

+push(o: E) : E

+search(o: Object) : int

java.util.Vector<E>

Creates an empty stack.

Returns true if this stack is empty.

Returns the top element in this stack.

Returns and removes the top element in this stack.

Adds a new element to the top of this stack.

Returns the position of the specified element in this stack.

Data1 Data2

Data1 Data1 Data2 Data3

Data1 Data2 Data3

Data1 Data2

Data3

Data1

Data2 Data1

The Stack

public static void main(String[] args) {Scanner s=new Scanner(System.in);String expr=s.nextLine();char c, c2;int value=0;Stack<Integer> operands=new Stack<Integer>();Stack<Character> operators=new Stack<Character>();for(int i=0;i<expr.length();i++) {

Using a Stack: Arithmetic Evaluation• To perform arithmetic evaluation (e.g., 1+2*(3-4))

we need to use 2 stacks– one will store the operands of the expression – in our

case, we will assume each operand is a single int digit, we store these in a Stack<Integer>

– one will store the operators of the expression which will be one character of +, -, *, /, ( or ), we store these in a Stack<Character>

c=expr.charAt(i); if(c>='0'&&c<='9') {

int x=(int)c-48;operands.push(new Integer(x));

}else if(c=='+'||c=='-') { while(!operators.empty()&&operators.peek()!='(') {

c2=(char)operators.pop();value=process(c2,operands);operands.push(new Integer(value));

} operators.push(new Character(c));}else if(c=='*'||c=='/') { while(operators.peek()=='*'||operators.peek()=='/'){

c2=(char)operators.pop();value=process(c2,operands);operands.push(new Integer(value));

} operators.push(new Character(c));}else if(c=='(') operators.push(new Character(c));

else if(c==')') { while(operators.peek()!='(') {

c2=(char)operators.pop();value=process(c2,operands);operands.push(new Integer(value));

} operators.pop();}

} System.out.println(expr + " = " + value); }

public static int process(char c, Stack<Integer> s) { int x2=s.pop().intValue();

int x1=s.pop().intValue();switch(c) { case '+': return x1+x2; case '-': return x1-x2; case '*': return x1*x2; case '/': return x1/x2;}return -9999; // error of some kind!

}}

Queues• A stack represents a FILO (or LIFO) structure• A queue represents a FIFO structure– We insert at one end (known as an enqueue operation)

and remove at the other (known as a dequeue operation)– We will refer to the ends as the front and rear

• In Java, the Queue class is an Interface which extends the Collection interface– Queue contains additional methods of offer (enqueue),

poll (dequeue), remove (dequeue), peek (return front element but do not remove it) and element (same as peek)• differences between poll and remove and between peek and

element are whether they throw an Exception or not if the queue is empty

The Queue

Data1 Data2

Data1 Data1 Data2 Data3

Data1 Data2 Data3

Data2 Data3

Data1

Data3

Data2 Data3

«interface» java.util.Queue<E>

+offer(element: E): boolean

+poll(): E

+remove(): E

+peek(): E

+element(): E

«interface» java.util.Collection<E>

Inserts an element to the queue.

Retrieves and removes the head of this queue, or null if this queue is empty.

Retrieves and removes the head of this queue and throws an exception if this queue is empty.

Retrieves, but does not remove, the head of this queue, returning null if this queue is empty.

Retrieves, but does not remove, the head of this queue, throwing an exception if this queue is empty.

Variations of Queues• PriorityQueue is a subclass of Abstract Queue and

implements Comparable– Items are inserted in order– Items are removed as with the Queue (from the front)– Since items are inserted in order, the item removed is always the

item of highest priority

• Deque is a subclass of Queue, is an interface, and adds methods to insert/remove from the ends– Deque is short for Double Queue (two sided queue)– This is implemented by calling upon Collection’s methods of

addFirst, removeFirst, addLast, removeLast

• LinkedList is a child of AbstractSequentialList (which implements List) but implements Deque– Although we can implement a queue or deque from an array, it is

more efficient to implement the queue using a linked list, thus the relationship between them