Classes SIMPLE_LIST_, LIST_, HASH_LIST_ and SORTED_LIST_ describe the containers of type LIST_ - the data structures in which the elements are arranged in a linear order: we know how they follow each other. Unlike an array, in which the linear order is determined by the array indices, the order in lists is determined by either an order in which the elements (items) are put into (SIMPLE_LIST_ and LIST_) or a total order relation based on the comparison of the elements (SORTED_LIST_) or their hash values - hash codes - (HASH_LIST_).
All the lists differ only in how their elements follow each other and that is why all of them have the same interface - only SORTED_LIST_ has some more additional features and SIMPLE_LIST_ has not features for backward traversing.
The instances of class SIMPLE_LIST_ represent so called singly linked lists - we can traverse these objects only in one direction: from the first element to the last one. Any new element is added to the end of the container (and becomes the last one at that time). The first element is the one put into a list earlier than all the others currently stored in the list. So, SIMPLE_LIST_ is based on a first_in, first-out, or FIFO, policy.
The instances of class LIST_ represent so called doubly linked lists. They differ from singly linked lists (SIMPLE_LIST_) only in one point: they can be traversed in the both directions: not only towards the last element but towards the first element also. In all other respects LIST_ and SIMPLE_LIST_ are the same (a new element is added to the end of the container also ...)
The instances of class HASH_LIST_ represent lists in which direct addressing into ordinary array takes place. Instead of requesting an array index directly, the array index is computed from the element. It is evident that the elements with smaller indices are ordered before those with bigger ones. The following algorithm for computing these indices are used in HASH_LIST_:
hash_index := x.hash_code \\ capacity + 1
where x is a descendant of class HASHABLE (part of the Eiffel Kernel), capacity is a feature of all the containers and \\ - integer remainder in Eiffel.
Class HASH_LIST_ describes a data structure which can give the programmer extremely fast operations of type search, put or remove. The efficiency of these operations depends solely on how well x.hash_code \\ capacity + 1 distributes the set of the elements to be stored among capacity slots. Formally the answer is very simple - 'hash_code' of class HASHABLE should be proper defined but, unfortunately, how to do that is beyond our discussion here ...
The instances of class SORTED_LIST_ represent data structures in which the elements are arranged according to the total order relation based on the comparing features - like `<` (less than) - defined or introduced in class COMPARABLE (part of the Eiffel Kernel). The smallest element is the first element in the linear order of SORTED_LIST_ and the largest one is the last element - all the others are surely put between them.
A FIFO policy is used for duplicates if they are allowed to be stored in a container of type LIST_.
While handling any list 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. The rest of the chapter are some extracts from the short (a kind of) forms of the classes.
indexing title: "The project-wide universal properties: the class is% %an ancestor to all the container classes" deferred class interface SIMPLE_CONTAINER_ feature -- Operations make (is_unique: BOOLEAN) -- tells the container if its entries must be unique deferred feature -- Queries empty: BOOLEAN -- is the container empty ? count: INTEGER -- gives the number of entries in the container or equally -- the number of the slots used for storing the entries deferred capacity: INTEGER -- gives the number of all the slots allocated in the container -- (all the containers may have not only slots occupied by the -- entries already put into but unused ones also) deferred invariant no_miracle: count >= 0 and then count <= capacity end
indexing title: "The manner of adding entries into non-keyed containers" deferred class interface CONTAINER_[G] inherit SIMPLE_CONTAINER_ feature -- Operations put (x: G) -- adds the new entry into the structure require dummy: False -- the real require's are to be defined later ... deferred end
indexing title: "Simple lists: containers with one element entries% %implementing a first-in, first-out policy and supporting% %only restricted traversal in one direction" class intarface SIMPLE_LIST_[G] inherit CONTAINER_[G] SIMPLE_TRAVERSABLE_ creation make feature -- Operations allocate_automatically -- switches the list 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 lists -- allocate memory automatically allocate_manually (new_capacity: INTEGER) -- forbids the list to allocate memory for new slots automatically -- and sets the total amount of slots allocated in the list 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_capacity: new_capacity >= count and then new_capacity > 0 make (is_unique: BOOLEAN) -- tells the container if its entries must be unique merge (other: like Current) -- puts all entries from 'other' into the list require no_obstacle: not is_protected; valid_argument: other /= Void ensure well_done: count = old count + other.count put (x: G) -- adds the entry into the list require else valid_argument: x /= Void; no_obstacle: not is_protected; uniqueness: unique_items implies not has_item (x) ensure then well_done: not empty and then has_item (x) remove (x: G) -- deletes the entry from the list require no_obstacle: not is_protected; valid_argument: x /= Void; valid_target: has_item (x) ensure well_done: count = old count - 1 remove_all (x: G) -- deletes the entry from the list together with all its -- duplicates if more than one copy is currently stored require no_obstacle: not is_protected; valid_argument: x /= Void; valid_target: has_item (x) ensure well_done: old count > count and then not has_item (x) search (x: G) -- looks for the element: after every successful attempt 'found' -- is set to True and 'found_item' - to the found element; -- in case of failure 'found' is set to False require valid_argument: x /= Void wipe_out -- removes all entries from the list require no_obstacle: not is_protected ensure well_done: empty feature -- Queries count: INTEGER -- number of the entries currently stored in the list or -- equally the number of slots used found: BOOLEAN -- was the last search successful ? found_item: G -- the entry found by the very last call to search; -- the value is valid if and only if 'found' = True unique_items: BOOLEAN -- must the entries be unique ? capacity: INTEGER -- gives the number of all slots allocated in the list (all types -- of the lists may have not only slots occupied by the entries -- already put into but unused ones also) count_of (x: G): INTEGER -- gives the number of the duplicates of the entry inclusive; if -- 'unique_items' = True then the number can be only zero or one require valid_argument: x /= Void ensure well_done: Result <= count cursor_at (x: G): SIMPLE_CURSOR_ -- delivers a new cursor positioned to the entry; if there is no -- such entry currently stored in the list Void is delivered require valid_argument: x /= Void ensure well_done: Result /= Void implies is_protected has_item (x: G): BOOLEAN -- is the entry currently stored in the list ? require valid_argument: x /= Void item_at (cs: SIMPLE_CURSOR_): G -- delivers the entry of the list the cursor is positioned to require proper_cursor: is_inside (cs) feature {SIMPLE_CURSOR_} first (cs: SIMPLE_CURSOR_) -- positions on the first item ensure then well_done: not empty implies has_item (item_at (cs)) forth (cs: SIMPLE_CURSOR_) -- moves one item forward ensure then well_done: not cs.is_finished implies has_item (item_at (cs)) end
indexing title: "Lists: containers with one element entries implementing% %a first-in, first-out policy and supporting traversal in% %the both directions" class interface LIST_[G] inherit SIMPLE_LIST_[G] undefine cursor redefine cursor_at, item_at, make TRAVERSABLE_ creation make feature -- Operations make (is_unique: BOOLEAN) -- tells the container if its entries must be unique feature -- Queries item_at (cs: CURSOR_): G -- delivers the entry of the list the cursor is positioned to cursor_at (x: G): CURSOR_ -- delivers a new cursor positioned to the entry; if there is no -- such entry currently stored in the list Void is delivered feature {CURSOR_} last (cs: CURSOR_) -- positions on the last item ensure then well_done: not empty implies has_item (item_at (cs)) back (cs: CURSOR_) -- moves one item backwards ensure then well_done: not cs.is_finished implies has_item (item_at (cs)) end
indexing title: "Hash lists: containers which store its one element entries% %widely using their ability to be associated with integers" class interface HASH_LIST_[G -> HASHABLE] inherit LIST_[G] rename make as list_make export {NONE} list_make redefine list_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 lists: containers which store their one element entries% %in a total relation order (ascending) based on the operations% %of class COMPARABLE from the Eiffel Kernel" class interface SORTED_LIST_[G -> COMPARABLE] inherit LIST_[G] redefine make creation make feature -- Operations make (is_unique: BOOLEAN) -- tells the container if its entries must be unique feature -- Queries cursor_after (x: G): CURSOR_ -- delivers a new cursor positioned to the entry closest to and -- greater than 'x' - the presence of entry 'x' is not essential -- but if currently there are at all no such entries in the list -- then Void is delivered require valid_argument: x /= Void ensure well_done: Result /= Void implies is_protected cursor_before (x: G): CURSOR_ -- delivers a new cursor positioned to the entry closest to and -- less than 'x' - the presence of entry 'x' is not essential -- but if currently there are at all no such entries in the list -- then Void is delivered require valid_argument: x /= Void ensure well_done: Result /= Void implies is_protected end