Classes TABLE_, HASH_TABLE_ and SORTED_TABLE_ describe the containers of type TABLE_ - the data structures in which the elements are arranged in a linear order: we know how they follow each other - just like ones describing by the containers of type LIST_. As was mentioned above these groups are very similar. The only difference is that a linear order of the elements is defined by their keys - not by the elements themselves. Every entry of the tables consists of two elements: an element or item itself and a key. The element is mainly only stored but the associated key is widely used for handling the entry.
Entries of an instance of class TABLE_ are handled basing on a FIFO policy. There is no much special in that - just like class LIST_.
The instances of class HASH_TABLE_ represent data structures in which direct addressing into ordinary array takes place. Instead of computing array index from the element like in HASH_LIST_ it is computed in HASH_TABLE_ from the key - the same algorithm is used.
The instances of class SORTED_TABLE_ represent data structures in which the elements are arranged according to the total order relation of their keys. The same technique as for the containers of type LIST_ is used.
Creation procedure make should be told whether the keys (not the items like in lists) are unique or not. This way allows us to use TABLE_ for "one to one" and "one to many" relations just by changing a parameter in a creation procedure. The different approach to group the tables in SET, TABLE and UNIQUE_TABLE (and correspondingly LIST and UNIQUE_LIST) seems also acceptable but introduces more classes and makes the system more difficult to use. So our approach seems to be better.
A FIFO policy is used for duplicates if they are allowed to be stored in a container of type TABLE_.
While handling any table the programmer can get in return not only the exceptions issued or raised by the Eiffel Kernel classes but also the container ones. These exceptions are being explained separately. Some extracts from the short (a kind of) forms of the classes are put below.
indexing title: "The manner of adding entries into keyed containers" deferred class interface KEYED_CONTAINER_[G, H] inherit SIMPLE_CONTAINER_ feature -- Operations put (x: G; k: H) -- adds the new entry into the structure require dummy: False -- the real require's are to be defined later ... deferred end
indexing title: "Tables: containers with two element entries (element or item% %itself and the associated key) implementing a FIFO policy and% %supporting traversal in the both directions" class interface TABLE_[G, H] inherit KEYED_CONTAINER_[G, H] TRAVERSABLE_ creation make feature -- Operations allocate_automatically -- switches the table to the mode of automatic memory allocation -- for new slots; it can be necessary only if 'allocate_manually' -- was called before because, by default, all types of the tables -- allocate memory automatically allocate_manually (new_capacity: INTEGER) -- forbids the table to allocate memory for new slots automatically -- and sets the total amount of slots allocated in the table to be -- equal to 'new_capacity' - being negligent after that in manual -- allocating extra slots for new entries to be put might lead to -- the exception of type SCFL ("container is full") require no_obstacle: not is_protected; proper_argument: new_capacity >= count and then new_capacity > 0 make (is_unique: BOOLEAN) -- tells the container if the keys of its entries must be unique merge (other: like Current) -- puts all entries from 'other' into the table require no_obstacle: not is_protected; valid_argument: other /= Void ensure well_done: count = old count + other.count put (x: G; k: H) -- adds the new entry into the structure require else valid_item: x /= Void; valid_key: k /= Void; no_obstacle: not is_protected; uniqueness: unique_keys implies not has_key (k) ensure then well_done: not empty and then has_key (k) remove (x: G; k: H) -- deletes the entry from the table require no_obstacle: not is_protected; valid_item: x /= Void; proper_key: k /= Void and then has_key (k) ensure well_done: count = old count - 1 remove_all (k: H) -- deletes all the entries items of which associated with key 'k' require no_obstacle: not is_protected; proper_key: k /= Void and then has_key (k) ensure well_done: old count > count and then not has_key (k) search (k: H) -- looks for the key: after every successful attempt 'found' is -- set to True and 'found_item' - to an element (item) associated -- with key 'k'; in case of failure 'found' is set to False require valid_argument: k /= Void wipe_out -- remove all entries from the table require no_obstacle: not is_protected ensure well_done: empty feature -- Queries count: INTEGER -- number of the entries currently stored in the table or -- equally the number of slots used found: BOOLEAN -- was the last search successful ? found_item: G -- the element (item) found by the last call to search; -- the value is valid if and only if 'found' = True unique_keys: BOOLEAN -- must the keys of the entries be unique ? capacity: INTEGER -- gives the number of all slots allocated in the table (all -- types of the tables may have not only slots occupied by -- the entries already put into but unused ones also) count_of (k: H): INTEGER -- gives the number of the entries items of which associated with -- key 'k'; if 'unique_items' = True then the number can be equal -- only to zero or one require valid_key: k /= Void ensure well_done: Result <= count current_keys: LIST_[H] -- delivers all the keys (without duplicates) currently stored in -- the table cursor_at (x: G; k: H): CURSOR_ -- delivers a new cursor positioned to the entry; if there is no -- such entry currently stored in the table Void is delivered require valid_item: x /= Void; proper_key: k /= Void ensure well_done: Result /= Void implies is_protected has_key (k: H): BOOLEAN -- is the entry currently stored in the table ? require valid_key: k /= Void item_at (cs: CURSOR_): G -- delivers the element or item of the entry the cursor is -- positioned to require proper_cursor: is_inside (cs) items_at_key (k: H): LIST_[G] -- delivers all the elements (items) currently stored in the -- table and associated with key 'k' require proper_key: k /= Void key_at (cs: CURSOR_): H -- the key of the entry the cursor is positioned to require proper_cursor: is_inside (cs) feature {CURSOR_} back (cs: CURSOR_) -- moves one item backwards ensure then well_done: not cs.is_finished implies has_key (key_at (cs)) first (cs: CURSOR_) -- positions on the first item ensure then well_done: not empty implies has_key (key_at (cs)) forth (cs: CURSOR_) -- moves one item forward ensure then well_done: not cs.is_finished implies has_key (key_at (cs)) last (cs: CURSOR_) -- positions on the last item ensure then well_done: not empty implies has_key (key_at (cs)) end
indexing title: "Hash tables: containers which store its two element entries% %(element or item itself and the associated key) widely using% %the ability of keys to be transformed into integers" class interface HASH_TABLE_[G, H -> HASHABLE] inherit TABLE_[G, H] rename make as table_make export {NONE} table_make redefine table_make creation make feature -- Operations make (is_unique: BOOLEAN; initial_capacity: INTEGER) -- tells the container if its entries must be unique and sets the -- initial amount of slots to be allocated for storing entries require proper_initial_slots: initial_capacity > 0 end
indexing title: "Sorted tables: containers which store their two element entries% %(element or item itself and the associated key) in a total% %relation order (ascending) based on the operations of class% %COMPARABLE (the Eiffel Kernel) being done on keys" class interface SORTED_TABLE_[G, H -> COMPARABLE] inherit TABLE_[G, H] redefine current_keys, make creation make feature -- Operations make (is_unique: BOOLEAN) -- tells the container if its entries must be unique feature -- Queries current_keys: LIST_[H] -- delivers all the keys (without duplicates) currently stored in -- the table cursor_after (k: H): CURSOR_ -- delivers a new cursor positioned to the entry the key of which -- is closest to and greater than 'k' - the presence of entry -- with key 'k' is not essential but if currently there are at -- all no such entries in the table then Void is delivered require proper_key: k /= Void ensure well_done: Result /= Void implies is_protected cursor_before (k: H): CURSOR_ -- delivers a new cursor positioned to the entry the key of which -- is closest to and less than 'k' - the presence of entry with -- key 'k' is not essential but if currently there are at all no -- such entries in the table then Void is delivered require proper_key: k /= Void ensure well_done: Result /= Void implies is_protected end