File: list.yo

package info (click to toggle)
c%2B%2B-annotations 13.02.02-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,576 kB
  • sloc: cpp: 25,297; makefile: 1,523; ansic: 165; sh: 126; perl: 90; fortran: 27
file content (241 lines) | stat: -rw-r--r-- 14,274 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
The ti(list) container hi(list container) implements a list data structure.
Before using a tt(list) container the header file tthi(list) must be included.

    The organization of a tt(list) is shown  in figure ref(listFig).
        figure(containers/list)(A list data-structure)(listFig)
    Figure ref(listFig)  shows that a list consists of separate
list-elements, connected by pointers. The list can be
    hi(list: traversal) traversed in two directions: starting at em(Front) the
list may be traversed from left to right, until the 0-pointer is reached at
the end of the rightmost list-element. The list can also be traversed from
right to left: starting at em(Back), the list is traversed from right to left,
until eventually the 0-pointer emanating from the leftmost list-element is
reached.

As a subtlety note that the representation given in figure ref(listFig) is not
necessarily used in actual implementations of the list. For example, consider
the following little program:
        verb(    int main()
    {
        list<int> l;
        cout << "size: " << l.size() << ", first element: " <<
                l.front() << '\n';
    })

When this program is run it might actually produce the output:
        verb(    size: 0, first element: 0)

Its front element can even be assigned a value. In this case the
implementor has chosen to provide the list with a hidden element. The list
actually is a em(circular)
 hi(list: circular) list, where the hidden element serves as terminating
element, replacing the 0-pointers in figure ref(listFig). As noted, this is a
subtlety, which doesn't affect the conceptual notion of a list as a data
structure ending in 0-pointers. Note also that it is well known that various
implementations of list-structures are possible (cf.
    i(Aho, A.V.), i(Hopcroft J.E.) and i(Ullman, J.D.), (1983)
    emi(Data Structures and Algorithms) (Addison-Wesley)).

Both lists and vectors are often appropriate data structures in situations
where an hi(storing data) unknown number of data elements must be
stored. However, there are some hi(rule of thumb) rules of thumb to follow
when selecting the appropriate  data structure.
    itemization(
    it() When most accesses are i(random), a tt(vector) is the preferred data
            structure. Example: in a program counting character frequencies in
            a textfile, a tt(vector<int> frequencies(256)) is the
            datastructure of choice, as the values of the received characters
            can be used as indices into the tt(frequencies) vector.
    it() The previous example illustrates a second rule of thumb, also
            favoring the tt(vector): if the number of elements is known in
            advance (and does not notably change during the lifetime of the
            program), the vector is also preferred over the list.
    it() In cases where i(insertions) or i(deletions) prevail and the data
            structure is large the list is generally preferred.
    )
    At present lists aren't as useful anymore as they used to be (when
computers were much slower and more memory-constrained).  Except maybe for
some rare cases, a tt(vector) should be the preferred container; even when
implementing algorithms traditionally using lists.

    Other considerations related to the choice between lists and vectors
should also be given some thought. Although it is true that the vector is able
to grow dynamically, the i(dynamic growth) requires data-copying.
Clearly, copying a million large data structures takes a considerable amount
of time, even on fast computers. On the other hand, inserting a large number
of elements in a list doesn't require us to
    i(copy non-involved data). Inserting a new element in a list merely
requires us to juggle some pointers. In figure ref(listAdd) this is shown: a
new element is inserted between the second and third element, creating a new
list of four elements.
        figure(containers/insertlist)(Adding a new element to a list)(listAdd)
    Removing an element from a list is also fairly easy. Starting again
from the situation shown in figure ref(listFig), figure ref(listDel) shows
what happens if element two is removed from our list. Again: only pointers
need to be juggled. In this case it's even simpler than adding an element:
only two pointers need to be rerouted.
        figure(containers/dellist)(Removing an element from a list)(listDel)
    To summarize the comparison between lists and vectors: it's probably best
to conclude that there is no clear-cut answer to the question what data
structure to prefer. There are rules of thumb, which may be adhered to. But if
worse comes to worst, a i(profiler) may be required to find out what's best.

    The tt(list) container offers the following constructors, operators, and
member functions:
    itemization(
    it() hi(list constructors) Constructors:
        itemization(
        it() The copy and move constructors are available;
        it() A tt(list) may be constructed empty:
    verb(list<string> object;)

As with the tt(vector), it is an error to refer to an element of an
empty list.
        it() A list may be initialized to a certain number of elements. By
            default, if the initialization value is not explicitly mentioned,
            the default value or default constructor for the actual data type
            is used. For example:
    verb(list<string> object(5, "Hello"s); // initialize to 5 Hello's
list<string> container(10);       // and to 10 empty strings)

it() A list may be initialized using a two iterators. To initialize a
            list with elements 5 until 10 (including the last one) of a
            tt(vector<string>) the following construction may be used:
    verb(extern vector<string> container;
list<string> object(&container[5], &container[11]);)

)
    it() The tt(list) does not offer specialized operators, apart from the
            standard operators for containers.
    it() The following hi(member function)member functions are available:
        itemization(
        itht(assign)(void assign(...)):
            quote(assigns new content to the list:)
            itemization(
            itt(assign(iterator begin, iterator end)) assigns the values at
                the iterator range rangett(begin, end) to the list;
            itt(assign(size_type n, value_type const &val)) assigns tt(n)
                copies of tt(val) to the list;
            )
        ithtq(back)(Type &back())(returns a reference to the last element in
            the list. It is the i(responsibility of the programmer) to use
            this member only if the list is not empty.)
        ithtq(begin)(list::iterator begin())(returns an iterator pointing to
            the first element in the list, returning tt(end) if the list is
            empty.)
        ithtq(clear)(void clear())(erases all elements from the list.)
        ithtq(emplace_back)(value_type &emplace_back(Args &&...args))
           (a tt(value_type) object is constructed from the member's
            arguments, and the newly created element is inserted beyond the
            last element of the list, returning a reference to the newly added
            element.) 
        ithtq(emplace_front)(value_type &emplace_front(Args &&...args))
           (a tt(value_type) object is constructed from the member's
            arguments, and the newly created element is inserted before the
            first element of the list, returning a reference to the newly added
            element.) 
        ithtq(empty)(bool empty())(returns tt(true) if the list contains no
            elements.)
        ithtq(end)(list::iterator end())(returns an iterator pointing beyond
            the last element in the list.)
        ithtq(erase)(list::iterator erase())(erases a specific range of
            elements in the list:)
            itemization(
            itt(erase(pos)) erases the element pointed to by tt(pos). The
                iterator tt(++pos) is returned.
            itt(erase(first, beyond)) erases elements indicated by the iterator
                range rangett(first, beyond). tt(Beyond) is returned.
            )
        ithtq(front)(Type &front())(returns a reference to the first element
            in the list. It is the responsibility of the programmer to use
            this member only if the list is not empty.)
        ithtq(get_allocator)(allocator_type get_allocator() const)(returns a
            copy of the allocator object used by the tt(list) object.)
        ithtq(insert)(... insert())(inserts elements into the list. The return
            value depends on the version of tt(insert) that is called:)
            itemization(
            itt(list::iterator insert(pos)) inserts a default value of type
                tt(Type) at tt(pos), tt(pos) is returned.
            itt(list::iterator insert(pos, value)) inserts tt(value) at
                tt(pos), tt(pos) is returned.
            itt(void insert(pos, first, beyond)) inserts the elements in the
                iterator range rangett(first, beyond).
            itt(void insert(pos, n, value)) inserts tt(n) elements having value
                tt(value) at position tt(pos).
            )
        ithtq(max_size)(size_t max_size())(returns the maximum number of
            elements this tt(list) may contain.)
        ithtq(merge)(void merge(list<Type> other))(this member function
            assumes that the current and other lists are sorted (see below,
            the member tt(sort)). Based on that assumption, it inserts the
            elements of tt(other) into the current list in such a way that the
            modified list remains sorted.  If both list are not sorted, the
            resulting list will be ordered `as much as possible', given the
            initial ordering of the elements in the two
            lists. tt(list<Type>::merge) uses tt(Type::operator<) to sort the
            data in the list, which operator must therefore be available.  The
            next example illustrates the use of the tt(merge) member: the list
            `tt(object)' is not sorted, so the resulting list is ordered 'as
            much as possible'.  
           verbinclude(-a examples/listmerge.cc) 
           A subtlety is that tt(merge) doesn't alter the list if the list
            itself is used as argument: tt(object.merge(object)) won't change
            the list `tt(object)'.)
        ithtq(pop_back)(void pop_back())(removes the last element from the
            list. The program aborts when called on an i(empty list).)
        ithtq(pop_front)(void pop_front())(removes the first element from the
            list. The program aborts when called on an i(empty list).)
        ithtq(push_back)(void push_back(value))(adds tt(value) to the end of
            the list.)
        ithtq(push_front)(void push_front(value))(adds tt(value) before the
            first element of the list.)
        ithtq(rbegin)(list::reverse_iterator rbegin())( returns a
            reverse_iterator pointing to the last element in the list.)
        ithtq(remove)(void remove(value))(removes all occurrences of tt(value)
            from the list. In the following example, the two strings
            `tt(Hello)' are removed from the list tt(object):
           verbinclude(-a examples/listremove.cc))
        ithtq(remove_if)(void remove_if(Predicate pred))(removes all
            occurrences from the list for which the predicate function or
            function object tt(pred) returns tt(true). For each of the objects
            stored in the list the predicate is called as tt(pred(*iter)),
            where tt(iter) represents the iterator used internally by
            tt(remove_if). If a function tt(pred) is used, its prototype
            should be tt(bool pred(value_type const &object))).
        ithtq(rend)(list::reverse_iterator rend())(this member returns a
            reverse_iterator pointing before the first element in the list.)
        ithtq(resize)(void resize())(alters the number of elements that are
            currently stored in the list:) itemization( itt(resize(n, value))
            may be used to resize the list to a size of tt(n). tt(Value) is
            optional. If the list is expanded and tt(value) is not provided,
            the extra elements are initialized to the i(default value) of the
            used data type, otherwise tt(value) is used to initialize extra
            elements.)
        ithtq(reverse)(void reverse())(reverses the order of the elements in
            the list. The element tt(back) becomes tt(front) and em(vice
            versa).)
        ithtq(size)(size_t size())(returns the number of elements in the
            list.)
        ithtq(sort)(void sort())(sorts the list. An example of its use is
            given at the description of the tt(unique) member function
            below. tt(list<Type>::sort) uses tt(Type::operator<) to sort the
            data in the list, which must therefore be available.)
        ithtq(splice)(void splice(pos, object))(transfers the content of
            tt(object) to the current list, starting the insertion at the
            iterator position tt(pos) of the object using the tt(splice)
            member. Following tt(splice), tt(object) is empty. For example:
         verbinclude(-a examples/listsplice.cc)
           Alternatively, tt(argument) may be followed by an iterator of
            tt(argument), indicating the first element of tt(argument) that
            should be spliced, or by two iterators tt(begin) and tt(end)
            defining the iterator-range rangett(begin, end) on tt(argument)
            that should be spliced into tt(object).)
        ithtq(swap)(void swap())(swaps two lists using identical data types.)
        ithtq(unique)(void unique())(operating on a sorted list, this member
            function removes all consecutively identical elements from the
            list. tt(list<Type>::unique) uses tt(Type::operator==) to identify
            identical data elements, which operator must therefore be
            available.  Here's an example removing all multiply occurring
            words from the list: verbinclude(-a examples/listunique.cc))
        )
)