001: #include <string>
002: #include <iostream>
003: #include <cassert>
004: 
005: using namespace std;
006: 
007: /* forward declarations */
008: template<typename T> class List;
009: template<typename T> class Iterator;
010: 
011: /**
012:    A class to hold the nodes of the linked list.
013: */
014: template<typename T>
015: class Node
016: {
017: public:
018:    /**
019:       Constructs a node for a given data value.
020:       @param s the data to store in this node
021:    */
022:    Node(T s);
023: private:
024:    T data;
025:    Node<T>* previous;
026:    Node<T>* next;
027: friend class List<T>;
028: friend class Iterator<T>;
029: };
030:    
031: /**
032:    An iterator denotes a position in the list or
033:    past the end of the list.
034: */
035: template<typename T>
036: class Iterator
037: {
038: public:
039:    /**
040:       Constructs an iterator that is not attached to any list.
041:    */
042:    Iterator();
043:    /** 
044:        Looks up the value at a position.
045:        @return the value of the Node to which the iterator 
046:        points
047:    */
048:    T operator*() const;
049:    /**
050:       Advances the iterator to the next position.
051:    */
052:    void operator++(int dummy);
053:    /**
054:       Moves the iterator to the previous position.
055:    */
056:    void operator--(int dummy);
057:    /**
058:       Compares two iterators.
059:       @param b the iterator to compare with this iterator
060:       @return true if this iterator and b are equal
061:    */
062:    bool operator==(Iterator<T> b) const;
063:    /**
064:       Compares two iterators.
065:       @param b the iterator to compare with this iterator
066:       @return true if this iterator and b are not equal
067:    */
068:    bool operator!=(Iterator<T> b) const;
069: private:
070:    Node<T>* position;
071:    Node<T>* last;
072: friend class List<T>;
073: };
074: 
075: /**
076:    A linked list of values of a given type.
077:    @param T the type of the list values
078: */
079: template<typename T>
080: class List
081: {
082: public:
083:    /**
084:       Constructs an empty list.
085:    */
086:    List();
087:    /**
088:       Constructs a list as a copy of another list.
089:       @param b the list to copy
090:    */
091:    List(const List<T>& b);
092:    /**
093:       Deletes all nodes of this list.
094:    */
095:    ~List();
096:    /**
097:       Assigns another list to this list.
098:       @param b the list to assign
099:       @return a reference to this list
100:    */
101:    List<T>& operator=(const List<T>& b);
102: 
103:    /**
104:       Appends an element to the list.
105:       @param s the value to append
106:    */
107:    void push_back(T s);
108:    /**
109:       Inserts an element into the list.
110:       @param iter the position before which to insert
111:       @param s the value to append
112:    */
113:    void insert(Iterator<T> iter, T s);
114:    /**
115:       Removes an element from the list.
116:       @param i the position to remove
117:       @return an iterator pointing to the element after the
118:       erased element
119:    */
120:    Iterator<T> erase(Iterator<T> i);
121:    /**
122:       Gets the beginning position of the list.
123:       @return an iterator pointing to the beginning of the list
124:    */
125:    Iterator<T> begin();
126:    /**
127:       Gets the past-the-end position of the list.
128:       @return an iterator pointing past the end of the list
129:    */
130:    Iterator<T> end();
131: 
132: private:
133:    /**
134:       Copies another list to this list.
135:       @param b the list to copy
136:    */
137:    void copy(const List<T>& b);
138:    /**
139:       Deletes all nodes of this list.
140:    */
141:    void free();
142:    
143:    Node<T>* first;
144:    Node<T>* last;
145: };
146: 
147: template<typename T>
148: List<T>::List()
149: {  
150:    first = NULL;
151:    last = NULL;
152: }
153: 
154: template<typename T>
155: List<T>::~List()
156: {  
157:    free();
158: }
159: 
160: template<typename T>
161: List<T>::List(const List<T>& b)
162: {  
163:    first = NULL;
164:    last = NULL;
165:    copy(b);
166: }
167: 
168: template<typename T>
169: List<T>& List<T>::operator=(const List<T>& b)
170: {  
171:    if (this != &b)
172:    {
173:       free();
174:       copy(b);
175:    }
176:    return *this;
177: }
178: 
179: 
180: template<typename T>
181: void List<T>::push_back(T s)
182: {  
183:    Node<T>* newnode = new Node<T>(s);
184:    if (last == NULL) /* list is empty */
185:    {  
186:       first = newnode;
187:       last = newnode;
188:    }
189:    else
190:    {  
191:       newnode->previous = last;
192:       last->next = newnode;
193:       last = newnode;
194:    }
195: }
196: 
197: template<typename T>
198: void List<T>::insert(Iterator<T> iter, T s)
199: {  
200:    if (iter.position == NULL)
201:    {  
202:       push_back(s);
203:       return;
204:    }
205: 
206:    Node<T>* after = iter.position;
207:    Node<T>* before = after->previous;
208:    Node<T>* newnode = new Node<T>(s);
209:    newnode->previous = before;
210:    newnode->next = after;
211:    after->previous = newnode;
212:    if (before == NULL) /* insert at beginning */
213:       first = newnode;
214:    else
215:       before->next = newnode;
216: }
217: 
218: template<typename T>
219: Iterator<T> List<T>::erase(Iterator<T> i)
220: {  
221:    Iterator<T> iter = i;
222:    assert(iter.position != NULL);
223:    Node<T>* remove = iter.position;
224:    Node<T>* before = remove->previous;
225:    Node<T>* after = remove->next;
226:    if (remove == first)
227:       first = after;
228:    else
229:       before->next = after;
230:    if (remove == last)
231:       last = before;
232:    else
233:       after->previous = before;
234:    iter.position = after;
235:    delete remove;
236:    return iter;
237: }
238: 
239: template<typename T>
240: Iterator<T> List<T>::begin()
241: {  
242:    Iterator<T> iter;
243:    iter.position = first;
244:    iter.last = last;
245:    return iter;
246: }
247: 
248: template<typename T>
249: Iterator<T> List<T>::end()
250: {  
251:    Iterator<T> iter;
252:    iter.position = NULL;
253:    iter.last = last;
254:    return iter;
255: }
256: 
257: template<typename T>
258: Iterator<T>::Iterator()
259: {  
260:    position = NULL;
261:    last = NULL;
262: }
263: 
264: template<typename T>
265: T Iterator<T>::operator*() const
266: {  
267:    assert(position != NULL);
268:    return position->data;
269: }
270: 
271: template<typename T>
272: void Iterator<T>::operator++(int dummy)
273: {  
274:    assert(position != NULL);
275:    position = position->next;
276: }
277: 
278: template<typename T>
279: void Iterator<T>::operator--(int dummy)
280: {  
281:    if (position == NULL)
282:       position = last;
283:    else 
284:       position = position->previous;
285:    assert(position != NULL);
286: }
287: 
288: template<typename T>
289: bool Iterator<T>::operator==(Iterator<T> b) const
290: {  
291:    return position == b.position;
292: }
293: 
294: template<typename T>
295: bool Iterator<T>::operator!=(Iterator<T> b) const
296: {  
297:    return position != b.position;
298: }
299: 
300: template<typename T>
301: Node<T>::Node(T s)
302: {  
303:    data = s;
304:    previous = NULL;
305:    next = NULL;
306: }
307: 
308: template<typename T>
309: void List<T>::copy(const List<T>& b)
310: {
311:    for (Iterator<T> p = b.begin(); p != b.end(); p++)
312:       push_back(*p);
313: }
314: 
315: template<typename T>
316: void List<T>::free()
317: {
318:    while (begin() != end())
319:       erase(begin());
320: }
321: 
322: int main()
323: {  
324:    List<string> staff;
325: 
326:    staff.push_back("Cracker, Carl");
327:    staff.push_back("Hacker, Harry");
328:    staff.push_back("Lam, Larry");
329:    staff.push_back("Sandman, Susan");
330: 
331:    /* add a value in fourth place */
332: 
333:    Iterator<string> pos;
334:    pos = staff.begin();
335:    pos++;
336:    pos++;
337:    pos++;
338: 
339:    staff.insert(pos, "Reindeer, Rudolf");
340: 
341:    /* remove the value in second place */
342: 
343:    pos = staff.begin();
344:    pos++;
345: 
346:    staff.erase(pos);
347: 
348:    /* print all values */
349: 
350:    for (pos = staff.begin(); pos != staff.end(); pos++)
351:       cout << *pos << "\n";
352: 
353:    return 0;
354: }