Contest Algorithms January 2016 3. Collections Contest Algorithms: 3. Collections 1 Overview 1. Class / Interface Libraries 2. Collection, Collections 3. List: ArrayList, LinkedList 4. Stack 5. Queue: Radix sort, Deque, PriorityQueue 6. Sets: TreeSet, HashSet 7. Maps: TessMap, HashMap 8. BitSet, Sieve of Eratosthenes Contest Algorithms: 3. Collections 2 1. Class/ Interface Libraries Map SortedMap List Collection Queue Set Dictionary Deque NavigableMap NavigableSet TreeMap HashTable HashMap BitSet EnumMap ArrayList WeakHashMap Arrays Contest Algorithms: 3. Collections TreeSet HashSet LinkedList LinkedHashSet Stack Collections ArrayDeque PriorityQueue LinkedHashMap Vector IdentityHashMap SortedSet interfaces and classes in the java.util package. Interfaces are in blue. 3 Kinds of Collections Collection--a group of objects, called elements Set--An unordered collection with no duplicates SortedSet--An ordered collection with no duplicates List--an ordered collection, duplicates are allowed Map--a collection that maps keys to values SortedMap--a collection ordered by the keys Note that there are two distinct hierarchies Collection Summary Contest Algorithms: 3. Collections 5 Map Summary Contest Algorithms: 3. Collections 6 Another Summary Contest Algorithms: 3. Collections 7 Contest Algorithms: 3. Collections 8 Generics A collection class takes an object type as a parameter: Collection<E> List<E> Stack<E> Set<E> A map takes two object type parameters: Map<K,V> 20-9 2. Collection<E> boolean isEmpty ( ) int size ( ) boolean contains (Object obj) boolean add (E obj) boolean remove (E obj) Iterator<E> iterator ( ) // ... other methods 20-10 Iterator “For Each” Loop Collection<String> words = new ArrayList<String>(); ... for (String word : words) { // process word > } A “for each” loop replaces the iterator technique 20-11 Bulk operations boolean containsAll(Collection c); boolean addAll(Collection c); boolean removeAll(Collection c); boolean retainAll(Collection c); void clear( ); return true if the object was modified Array operations Object[ ] toArray( ); creates a new array of Objects Object[ ] toArray(Object a[ ]); provide the array that is filled Examples: Object[ ] a = coll.toArray(); String[ ] a = (String[ ]) coll.toArray(new String[0]); The Collections class Not the same as the Collection interface Static utility methods to operate on Collection objects Collections class methods Binary search Sorting Copying Min/Max Reverse Shuffle Frequency / disjoint Synchronization Unmodifiable Singletons Fill Constants for empty… List Set Map Etc. see UseCollections.java 3. List<E> «interface» Collection // All Collection<E> methods, plus: E get (int i) E set (int i, E obj) void add (int i, E obj) E remove (int i) int indexOf (E obj) int lastIndexOf(E obj) List subList(int from, int to) «interface» List additional positional access and searching methods 20-16 «interface» ArrayList List ArrayList LinkedList Represents a list as a dynamic array. Provides faster random access to the elements Implements all the methods of List<E> see UseArrayList.java a0 a1 a2 ... an-1 20-17 Code ArrayList<Integer> v = new ArrayList<Integer>(); v.add(10); v.add(7); v.add(2); v.add(15); v.add(4); // sort ascending Collections.sort(v); System.out.println(v); // [2, 4, 7, 10, 15] int pos = Collections.binarySearch(v, 7); Contest Algorithms: 3. Collections // 2 18 «interface» LinkedList List and Queue, Deque ArrayList LinkedList Represents a list as a doubly-linked list a0 a1 a2 ... an-1 Implements all the methods of List<E> Faster insertions and deletions 20-19 Additional methods specific to LinkedList: void addFirst (E obj) void addLast (E obj) E getFirst ( ) E getLast ( ) E removeFirst ( ) E removeLast ( ) see UseLinkedList.java ArrayList vs. LinkedList Implements a list as an array Implements a list as a doubly-linked list + Provides random access to the elements - No random access to the elements — needs to traverse the list to get to the i-th element - Inserting and removing elements requires shifting of subsequent elements + Inserting and removing elements is done by rearranging the links — no shifting - Needs to be resized when runs out of space + Nodes are allocated and released as necessary 20-21 ArrayList LinkedList get(i) and set(i, obj) O(1) O(n) add(i, obj) and remove(i) O(n) O(n) add(0, obj) O(n) O(1) add(obj) O(1) O(1) contains(obj) O(n) O(n) 20-22 for (int i = 0; i < list.size(); { Object x = list.get (i); ... } Works well for an ArrayList O(n); inefficient for a LinkedList O(n2) i++) for (Object x : list) { ... } Work well for both an ArrayList and a LinkedList O(n) 20-23 Code see CheckPali.java CheckPali.java uses a list to check if the letter of an input string are a paalindrome Contest Algorithms: 3. Collections 24 4. Stack<E> boolean isEmpty ( ) E push (E obj) E pop ( ) E peek ( ) see UseStackQueue.java Returns the top element without removing it from the stack 20-25 Code see ConvertInteger.java ConvertInteger.java uses a stack to convert a decimal into any base between 2 and 16: Contest Algorithms: 3. Collections 26 5. Queue<E> «interface» Queue and List, Deque boolean offer (E e) LinkedList Insert e at rear of queue; return true if worked E remove () Remove and return front entry; exception if none E poll () Remove and return front entry; null if none see UseStackQueue.java E peek () Return front entry without removing; null if none E element () Return front entry without removing; exception if none 27 Part of the Collection hierarchy, so ... Offers many other methods, including: add size isEmpty iterator 28 Radix Sort • Radix sort uses the digits in each array element to sort the array. • The array elements are passed to ten queues (index 0 to 9) using each element's digit as the index. • Elements are copied from the queues back to the original array, in partially sorted order. Radix Sort Example Array: [91, 6, 85, 15, 92, 35, 30, 22, 39] use the units digit in each element (100 digit) After Pass 0: [30, 91, 92, 22, 85, 15, 35, 6, 39] partially sorted use the tens digit in each element (101 digit) After Pass 1: [6, 15, 22, 30, 35, 39, 85, 91, 92] fully sorted • The i-th pass distributes the array elements into one of the 10 queues by looking at the digit in each element corresponding to the power 10i. in pass 0, look at units digit (100) in pass 1, look at tens digit (101) • Radix sort must carry out d passes, one for each digit in the largest element e.g. if the largest element is 92, then d = 2 passes; if largest is142, then d == 3 passes Code see UseRadixSort.java private static final int NUM_VALS = 50; public static void main(String[] args) { int[] arr = new int[NUM_VALS]; // initialize array with random numbers in range 0 - 99999 Random rnd = new Random(); for (int i = 0; i < NUM_VALS; i++) arr[i] = rnd.nextInt(100000); // apply the radix sort and output the sorted array radixSort(arr, 5); displayArray(arr); } // end of main() Contest Algorithms: 3. Collections 32 public static void radixSort(int[] arr, int d) { // an arraylist of 10 empty queues ArrayList<LinkedList<Integer>> qs = new ArrayList<>(); for (int i=0;i < 10; i++) qs.add( new LinkedList<Integer>()); // the current digit is found by dividing by 10^power int power = 1; for (int i=0;i < d;i++) { distribute(arr, qs, power); collect(qs, arr); power *= 10; } } // end of radixSort() Contest Algorithms: 3. Collections 33 private static void distribute(int[] arr, ArrayList<LinkedList<Integer>> qs, int power) { // insert each element into the right queue for (int i=0; i < arr.length; i++) qs.get((arr[i] / power) % 10).add(arr[i]); } private static void collect(ArrayList<LinkedList<Integer>> qs, int[] arr) // gather elements from the queues and copy back to the array { int i=0; for (LinkedList<Integer> q : qs) while (!q.isEmpty()) arr[i++] = q.remove(); } Contest Algorithms: 3. Collections 34 Execution Radix Sort Efficiency The runtime efficiency of radixSort() is O(radix*n) where the list has n elements and the biggest element has radix digits a fast linear sorting algorithm But radixSort() uses a lot of memory it needs one queue for each digit If we are sorting strings, then we will need 1 queue for each different letter (62+ queues) see UseStackQueue.java Deque ("deck") «interface» Queue «interface» Deque is a queue where you can insert and remove elements from both ends short for Double Ended Queue Deque ArrayDeque ArrayDeque stores its elements in a dynamic 'circular' array always faster than LinkedList for random access less node creation (on average) than LinkedList, so a bit faster for insertion Contest Algorithms: 3. Collections 37 «interface» Priority Queues Items are processed in order of priority, NOT in order of addition. Queue PriorityQueue The same methods as in Queue: isEmpty, add, remove, peek add and remove run in O(log n) time; peek runs in O(1) time Works with Comparable objects or takes a comparator as a parameter; see code 20-38 Code see Pair.java public class Pair< X, Y > { private X x; private Y y; public Pair(X x, Y y) { this.x = x; this.y = y; } public X getX() { return x; } public Y getY() { return y; } public void setX(X el) { x = el; } public void setY(Y el) { y = el; } public String toString() { return "(" + x + ", " + y + ")"; } // end of Pair class Contest Algorithms: 3. Collections } 39 see UsePriorityQueue.java PriorityQueue< Pair<Integer,String>> pq = new PriorityQueue< Pair<Integer,String>>(7, // initial capacity new Comparator< Pair<Integer,String>>() { public int compare( Pair<Integer,String> i, Pair<Integer,String> j) { return j.getX() - i.getX(); } // order based on the x in Pair, largest first. }); // enter these 7 money-name pq.offer( new Pair<Integer, pq.offer( new Pair<Integer, pq.offer( new Pair<Integer, pq.offer( new Pair<Integer, pq.offer( new Pair<Integer, pq.offer( new Pair<Integer, pq.offer( new Pair<Integer, : Contest Algorithms: 3. Collections pairs String>(100, "john") ); // inserting is O(log n) String>(10, "billy") ); String>(20, "andy") ); String>(100, "steven") ); String>(70, "felix") ); String>(2000, "grace") ); String>(70, "martin") ); 40 /* priority queue will arrange items based on the first x in Pair, largest first. If first keys tie, then the second key is used, largest first. */ for (Pair<Integer,String> p : pq) System.out.println(p); // print out the top 3 with most money Pair<Integer, String> result = pq.poll(); /* O(1) to access the top / max element + O(log n) removal of the top and repair of the structure */ System.out.println(result.getY() + " has $" + result.getX()); // prints grace has $2000 (2000, grace) (100, steven) (100, john) (10, billy) (70, felix) (20, andy) (70, martin) result = pq.poll(); System.out.println(result.getY() + " has $" + result.getX()); // prints steven has $100 result = pq.poll(); System.out.println(result.getY() + " has $" + result.getX()); // prints john has $100 Contest Algorithms: 3. Collections 41 6. Sets A set is a collection without duplicate values What is a “duplicate” depends on the implementation Designed for finding a value quickly «interface» Collection «interface» Set TreeSet 20-42 HashSet «interface» TreeSet<E> Set TreeSet HashSet Works with Comparable objects (or takes a comparator as a parameter) contains(), add(), and remove() run in O(log n) time for-each returns elements in ascending order Methods: headset, tailSet, subset() use this ordering see UseMapSet.java 20-43 Code see TreeSetWithComparator.java public class TreeSetWithComparator { public static void main(String a[]) { TreeSet<String> ts = new TreeSet<String>(new StringComp()); ts.add("RED"); ts.add("ORANGE"); ts.add("BLUE"); ts.add("GREEN"); > java TreeSetWithComparator System.out.println(ts); [BLUE, GREEN, ORANGE, RED] BLUE for(String s : ts) GREEN System.out.println(" " + s); ORANGE } RED } class StringComp implements Comparator<String> { public int compare(String s1, String s2) { return s1.compareTo(s2); } } Contest Algorithms: 3. Collections 44 «interface» HashSet<E> Set TreeSet HashSet Works with objects with hashCode() and equals() Implements a set as a hash table contains(), add(), and remove() run in O(1) time faster than TreeSet for-each returns elements in no particular order 20-45 7. Maps A map stores data in key-value pairs. A key acts like an index to locate the corresponding value in the map a map is also called an associative array «interface» Map TreeMap HashMap Map<K, V> Methods «interface» Map TreeMap HashMap boolean isEmpty ( ) int size ( ) V get (K key) V put (K key, V value) V remove (K key) boolean containsKey (K key) Set<K> keySet ( ) Map.Entry<K, V> entrySet() collection views; replace iteration 20-47 Map Collection Views A map does not have an iterator/for-each for accessing its elements. Instead we can use collection views, which are sets that act on the original map the keySet collection view a set of key entries the entrySet collection view a set of key-value entries A view is backed by the original Map, so any changes done to the keyset / entrySet will affect the Map as well. Code see UseMapSet.java System.out.println( userScores.keySet()); // prints keys in ascending order if using TreeSet // iterate through the map using entry set; // accessed in ascending key order if using TreeSet for(Map.Entry<String,Integer> entry : userScores.entrySet()) { String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(" " + key + " => " + value); } Contest Algorithms: 3. Collections 49 «interface» TreeMap<K,V> Map TreeMap HashSet Takes a Comparator as a parameter also works with keys thatimplement Comparable containsKey(), get(), and put() run in O(log n) time for-each on entrySet returns elements in ascending order by key submap() uses this ordering 20-50 TreeMap.submap() SortedMap subMap(int fromKey, int toKey) returns a portion of the TreeMap whose keys range from fromKey (inclusive) to toKey (exclusive) The SortedMap returned by this method is backed by the original TreeMap any changes made to SortedMap will change the original TreeMap as well Contest Algorithms: 3. Collections 51 Code see UseMapSet.java // display data between ["f".."m") // ('felix' is included, martin' is excluded) SortedMap<String, Integer> res = userScores.subMap("f", "m"); System.out.println(res.keySet()); System.out.println(res.values()); Contest Algorithms: 3. Collections // prints [felix, grace, john] // prints [82, 75, 78] 52 «interface» HashMap<K,V> Map TreeMap HashMap Works with key objects with hashCode() and equals() Implements the key set as a hash table containsKey(), get(), and put() run in O(1) time faster than TreeMap for-each on entrySet returns elements in no particular order 20-53 8. BitSet An alternative to boolean[], with many useful methods: BitSet(int nbits) constructor, all nbits bits are false initially void set(int) set a bit at index pos; may dynamically resize set boolean get(int) get bit status at index pos void clear(int) clear a bit (set to false) at index pos void or(BitSet) compute logical-or of two bitsets void and(BitSet) void xor(BitSet) String toString(): nice list of comma-separated on-positions Boolean equals(Object): test if two bitsets are the same Code BitSet bs1 = new BitSet(20); bs1.set(1); bs1.set(4); BitSet bs2 = new BitSet(20); bs2.set(4); bs2.set(5); System.out.println("bits 1 = " + bs1); System.out.println("bits 2 = " + bs2); if(bs1.equals(bs2)) System.out.println ("bits1 == bits2\n"); else System.out.println ("bits1 ! = bits2\n"); see UseBitSet.java > java UseBitSet Bits 1 = {1, 4} Bits 2 = {4, 5} bits1 ! = bits2 ANDing bits1 and bits2 bits1 = {4} // logically AND the first two BitSets bs1.and(bs2); System.out.println("ANDing bits1 and bits2"); System.out.println("bits1 = " + bs1.toString()); Contest Algorithms: 3. Collections 55 BitSet Implementation BitSet uses a single bit to a boolean value. Internally the bits are managed inside a long[] But BitSet only supports int keys, so is limited to 232-1 bits BitSet is much more space efficient than a boolean[] since Java uses an entire byte to store each element in the boolean array! http://chrononsystems.com/blog/ hidden-evils-of-javas-byte-array-byte Contest Algorithms: 3. Collections 56 A graph showing the space used by boolean[] and BitSet for 100,000 elements: Contest Algorithms: 3. Collections 57 The Sieve of Eratosthenes The process is a systematic way of selecting values we know are prime and crossing out values we know must be composite. Create a list of every number from 2 up to as big as we want (e.g to 29) 1. Cross out all multiples of 2: Contest Algorithms: 3. Collections 58 Go to next uncrossed number == 3. Cross out all multiples of 3: Go to next uncrossed number == 5. Cross out all multiples of 5: Contest Algorithms: 3. Collections 59 Continue until the end of the list is reached: The uncrossed numbers are the primes from 2 to 29. Contest Algorithms: 3. Collections 60 Bitset Version of Sieve see SieveBitSet.java Represent the list as a Bitset Start by setting all the bits to true, and then sieve by setting bit multiples to false. The advantages of this approach is that the BitSet can represent a very large number sequence, and is quite fast too. Contest Algorithms: 3. Collections 61 BitSet sieve = new BitSet(1024); int size = sieve.size(); // set all bits from 2 to 1023 to true for (int i = 2; i < size; i++) sieve.set(i); // to true // start sieving int finalBit = (int) Math.sqrt(size); // can stop at √n, not n for (int i = 2; i < finalBit; i++) { if (sieve.get(i)) { for (int j = 2 * i; j < size; j += i) sieve.clear(j); // to false } } : Contest Algorithms: 3. Collections 62 // display prime numbers from 2 to 1023 int counter = 0; System.out.println("--------- Primes from 2 to 1023 ---------"); for (int i = 2; i < size; i++) { if (sieve.get(i)) { System.out.printf("%4d", i); System.out.print(++counter % 7 == 0 ? "\n" : " "); } } Contest Algorithms: 3. Collections 63 Contest Algorithms: 3. Collections 64