Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Making Linked Lists More User-Friendly-3 : Page 3

Step 2: Dealing with Sequences
Up until now I have exemplified list operations that operate on a single element at a time. list supports sequence operations as well. These operations enable you to traverse, fill, sort and reverse a list. Iteration is easy. The begin() and end() member functions return iterators pointing at the list's beginning and end, respectively. Use them to access all the list's elements sequentially. Note that we use a const_iterator instead of a plain iterator because the iteration process in this case doesn't modify the list:

list<int>::const_iterator it; for(it=li.begin(); it!=li.end(); ++it) { cout << *it << endl; // each element on a separate line }

The assign() member function fills a list with the contents of another sequence such as a vector or an array. It takes two input iterators that mark the sequence's beginning and end, respectively. In the following example, we fill a list with the elements of an array:

int arr[3] = {10,20,30}; li.assign( &arr[0], &arr[3]);

You can merge two lists into one. The merge() member function takes a reference to another list object:

list <int> x; //..fill x li.merge(x); // merge the elements of x into li

merge() merges x into li. x is empty after the merge operations. To erase one or more elements, use the erase() member function. This function has two overloaded versions. The first version takes an iterator and erases the element to which it points. The second version takes two iterators that mark the beginning and the end of the sequence to be erased. Suppose we have a list of 10 elements and we want to remove all the elements but the first two. We use erase() as follows:

list<int>::it=li.begin(); ++it; ++it; // advance to third element li.erase(it, li.end()); // erase elements 3 - 10

Step 3: Supporting User-Defined Types
The generic nature of list enables you to define specializations, or instances, of user-defined types. For example, you may create lists of strings and Date objects like this:

#include <string> #include "Date.h" list<std::string> ls; list <Date> ld;

Operations that require element comparison such as sort() and unique() use the overloaded < operator. If you intend to use any of these algorithms with lists, define a matching overloaded version of this operator for your class (read more on overloading binary operators here):

bool operator < (const Date& d1, const Date& d2); ld.sort(); // OK, using overloaded < operator

Note that in general, sorting a list is less efficient than sorting a vector or a queue. Therefore, if you need to sort elements frequently, you probably shouldn't use a list in the first place. The same is true for reverse(), which is also supported:

ld.reverse(); for(it=ld.begin(); it!=ld.end(); ++it) { cout << *it << endl; // descending order }

Danny Kalev is a system analyst and software engineer with 13 years of experience, specializing in C++ and object-oriented analysis and design. He is a member of the ANSI C++ standardization committee and the author of ANSI/ISO C++ Professional Programmer's Handbook (Que, 1999, ISBN: 0789720221).
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date