11 Map ADTs Map concepts. Map applications. A map ADT: requirements, contract. Implementations of maps: using arrays, linked lists, BSTs. Maps in the Java class library. © 2001, D.A. Watt and D.F. Brown
Map concepts (1) A map is a collection of entries, which have distinct keys, and whose order is insignificant. Each entry is a tuple consisting of a key field and a value field. More generally, an entry may have several value fields and/or several key fields. Here we assume one key field and one value field.
Map concepts (2) Examples of maps: value field key field EC = country currency DE mark FR franc IT lira NL guilder BE LU Roman = letter value I 1 V 5 X 10 L 50 C 100 D 500 M 1000 NAFTA = country currency CA dollar US MX peso
Map concepts (3) The cardinality of a map m is the number of entries in m. This is written #m. E.g.: #NAFTA = 3 The empty map has cardinality zero. We can look up a map for a given key, to obtain the corresponding value (if any). E.g.: Looking up ‘X’ in map Roman gives 10. Looking up ‘A’ in map Roman gives nothing.
Map concepts (4) We can overlay map m1 by map m2. The result contains all entries from both m1 and m2, except that where both maps contain entries with the same key, the result contains the entry from m2 only. E.g.: count1 = state winner New York Gore Texas Bush Florida Result of overlaying count1 by count2 = state winner New York Gore Texas Bush Ohio Florida count2 = state winner Ohio Bush Florida
Map applications Relational database: Telephone directory: A relation is a collection of tuples. If a relation has a key field, all tuples must have distinct keys. The tuples are in no particular order. Thus a relation is really a map. Telephone directory: Each entry consists of a name, address, and telephone number. Several entries may share the same name, but each entry must have a unique name–address combination. The entries could be in any order. (They are typically sorted by name and address, to make lookup fast, but that is not essential.) Thus a telephone directory is a map in which the key field is the name–address combination.
Map ADT: requirements Requirements: It must be possible to make a map empty. It must be possible to test whether a map is empty. It must be possible to test whether a map contains an entry with a given key. It must be possible to look up the value corresponding to a given key in a map. It must be possible to add a new entry to a map or to replace an existing entry. It must be possible to remove an entry from a map, given its key. It must be possible to test whether two maps are equal. It must be possible to compute the overlay of two maps. It must be possible to traverse a map.
Map ADT: contract (1) Possible contract: public interface Map { // Each Map object is a map whose keys and values are objects. //////////// Accessors //////////// public boolean isEmpty (); // Return true if and only if this map is empty. public int size (); // Return the cardinality of this map. public Object get (Object key); // Return the value in the entry with key in this map, or null if // there is no such entry.
Map ADT: contract (2) Possible contract (continued): public boolean equals (Map that); // Return true if this map is equal to that. public Set keySet (); // Return the set of all keys in this map. //////////// Transformers //////////// public void clear (); // Make this map empty. public Object remove (Object key); // Remove the entry with key (if any) from this map. Return the // value in that entry, or null if there was no such entry.
Map ADT: contract (3) Possible contract (continued): public Object put (Object key, Object val); // Add the entry (key, val) to this map, replacing any existing // entry whose key is key. Return the value in that entry, or null // if there was no such entry. public void putAll (Map that); // Overlay this map with that, i.e., add all entries of that to // this map, replacing any existing entries with the same keys. }
Implementation of small-integer-key maps using key-indexed arrays (1) If the keys are known to be small integers, in the range 0…m–1, represent the map by: an array vals of length m, such that vals[k] contains a value v if and only if (k, v) is a entry of the map. 1 m–1 Invariant: value? 2 Empty map: 1 m–1 2
Implementation using key-indexed arrays (2) Illustration (m = 20): code module 01 CS1 02 CS2 10 DB 11 OOP 12 ADS 14 OS 16 HCI is represented by CS1 CS2 1 2 3 OOP ADS OS DB 10 11 12 14 15 13 HCI 16 17 18 19
Implementation using key-indexed arrays (3) Summary of algorithms and time complexities: Operation Algorithm Time complexity get inspect array component O(1) remove make array component null put update array component putAll pairwise update all array components O(m) equals pairwise equality test
Implementation of maps using arrays (1) Represent a bounded map (cardinality maxcard) by: a variable card, containing the current cardinality an array entries of length maxcard, containing the map entries in entries[0… card–1]. Keep the array sorted by key. entry with greatest key unoccupied entry with least key 1 card–1 card Invariant: entry maxcard–1 Empty map: 1 card=0 maxcard–1
Implementation using arrays (2) Illustration (maxcard = 9): element number He 2 Ne 10 Ar 18 Kr 36 Xe 54 Rn 86 is represented by 4 5 Xe 54 Rn 86 card=6 7 2 3 Ne 10 Kr 36 1 He 2 Ar 18 8
Implementation using arrays (3) Summary of algorithms and time complexities: Operation Algorithm Time complexity get binary search O(log n) remove binary search, then array deletion O(n) put binary search, then array insertion putAll variant of array merge O(n1+n2) equals pairwise equality test O(n2)
Implementation of maps using SLLs (1) Represent an (unbounded) map by: a variable card, containing the current cardinality an SLL, containing one entry per node. Keep the SLL sorted by key. entry with greatest key entry with least key Invariant: entry Empty map:
Implementation using SLLs (2) Illustration: element number He 2 Ne 10 Ar 18 Kr 36 Xe 54 Rn 86 is represented by Xe 54 Rn 86 Ne 10 Kr 36 He 2 Ar 18
Implementation using SLLs (3) Summary of algorithms and time complexity: Operation Algorithm Time complexity get SLL linear search O(n) remove SLL linear search, then deletion put SLL linear search, then insertion putAll variant of SLL merge O(n1+n2) equals pairwise equality test O(n2)
Implementation of maps using BSTs (1) Represent an (unbounded) map by a BST whose elements are the entries. Use only the keys to order the entries. Invariant: Empty map:
Implementation using BSTs (2) Illustration: element number He 2 Ne 10 Ar 18 Kr 36 Xe 54 Rn 86 could be represented by Xe 54 Rn 86 Ne 10 Kr 36 He 2 Ar 18
Implementation using BSTs (3) Summary of algorithms and time complexity: Operation Algorithm Time complexity get BST search O(log n) best O(n) worst remove BST deletion put BST insertion putAll BST merge O(n2 log (n1+n2)) best O(n1 n2) worst equals traversal of one BST, searching for each key in the other BST O(n1 log n2) best O(n1 n2) worst
Summary of map implementations Operation Key-indexed array repr- esentation Array repr- esentation SLL repr- esentation BST representation get O(1) O(log n) O(n) O(log n) best O(n) worst remove put putAll O(m) O(n1+n2) O(n2 log (n1+n2)) best O(n1 n2) worst equals O(n2) O(n1 log n2) best O(n1 n2) worst
Maps in the Java class library The java.util.Map interface is similar to the Map interface above. The java.util.TreeMap class implements the java.util.Map interface, representing each map by a search tree. The java.util.HashMap class implements the java.util.Map interface, representing each map by an open-bucket hash table (see 13).
Example 1: mobile telephone directory (1) Consider a mobile phone equipped with a memory, keypad, and display. The memory contains a directory, in which each entry consists of a (short) name and telephone number. All names must be distinct. The directory handler remembers the name most recently entered on the keypad. The directory handler remembers the telephone number most recently entered on the keypad or retrieved from the directory.
Example 1 (2) Implementation outline: public class DirectoryHandler { private Map directory; private String currentName = "?"; private String currentTelNum = "?";
Example 1 (3) Implementation outline (continued): public void lookupCurrentName () { // Look up the telephone number (if any) corresponding to // currentName, and set currentTelNum accordingly. String tel = (String) directory.get(currentName); display.write(currentName + " " + (tel != null ? tel : "NOT FOUND")); if (tel != null) currentTelNum = tel; }
Example 1 (4) Implementation outline (continued): public void addCurrentNameAndNumber () { // Add an entry consisting of currentName and // currentTelNum. String tel = (String) directory.get(currentName); if (tel != null) { … // Confirm that the user wishes to replace the existing // entry for currentName. } directory.put(currentName, currentTelNum); display.write(currentName + " " + currentTelNum + " ADDED"); }
Example 1 (5) Implementation outline (continued): public void removeCurrentName () { // Remove the entry corresponding to currentName. String tel = (String) directory.remove(currentName); display.write(currentName + " " + (tel != null ? "REMOVED" : "NOT FOUND")); } }