7 4 9Containers This chapter describes standard class templates used to represent containers for more efficient management of object collections.These include ■ sequences, such as lists
Trang 17 4 9
Containers
This chapter describes standard class templates used to represent containers for more efficient management of object collections.These include
■ sequences, such as lists and double ended queues
■ container adapters, such as stacks, queues, and priority queues
■ associative containers, such as sets and maps, and
■ bitsets
Besides discussing how to manage containers, we will also be looking at sample applications, such as bitmaps for raster images, and routing techniques
Trang 2750 C H A P T E R 3 3 C O N T A I N E R S
■ CONTAINER TYPES
Sequences and associative containers
etc.
Sets
Containers Containers
Trang 3䊐 What is a Container?
Containers are used to store objects of the same type and provide operations with which these objects can be managed These operations include object insertion, deletion, and retrieval Memory is allocated for containers dynamically at runtime Containers thus provide a safe and easy way to manage collections of objects
The C++ standard library provides various class templates for container management
in the Containers Library These classes can be categorized as follows:
■ sequential containers, or sequences, where the objects are arranged sequentially
and access to an object can either be direct or sequential
■ associative containers, where the objects are generally organized and managed in
a tree structure and can be referenced using keys
䊐 Sequences
Sequential containers are distinguished by the operations defined for them, which are either generic or restricted Restricted operations, such as appending at the end of a con-tainer, have constant runtimes That is, the runtime is proportional to a fixed period of time and does not depend on the number of objects in the container
The following are sequential containers:
■ arrays, which provide the same operations as C arrays but increase and decrease
in size dynamically, in contrast to C arrays
■ queues, which are managed on the FIFO (First In First Out) principle The first
element to be inserted is also removed first
■ stacks, which are managed on the LIFO (Last In First Out) principle The last
element to be inserted is removed first
䊐 Associative Containers and Bitsets
Associative containers comprise sets, which allow quick access to objects via sortable keys, and maps, which maintain efficient object/key pairs.
There are also so-called bitsets, which represent bit sequences of a given length and
provide bitwise operators, with which bits can be manipulated
Trang 4752 C H A P T E R 3 3 C O N T A I N E R S
■ SEQUENCES
Operations for sequences
Class Template Time needed to insert or
remove an object
vector<class T, class Allocator = allocator<T> >
At the end: constant.
At the beginning or in the middle: linear.
In all positions: constant.
At the beginning or end: constant.
In the middle: linear
list<class T, class Allocator = allocator<T> >
deque<class T, class Allocator = allocator<T> >
Container adapters
Class Template Insertion Deletion
stack<class T, class Container = dequeue<T> >
at the end at the end
queue<class T, class Container = dequeue<T> >
at the end at the
beginning
at the beginning
priority_queue<class T, class Container = vector<T>, Compare=less<T> >
priority based
Sequences and header files
vector<T, Allocator>
list<T, Allocator>
deque<T, Allocator>
stack<T, Container>
queue<T, Container>
priority_queue<T,
<vector>
<list>
<deque>
<stack>
<queue>
<queue>
Trang 5䊐 Representing Sequences
The Containers Library defines so-called container classes representing containers These
are class templates parameterized by the type Tof the objects to be managed
Three basic class templates are defined for sequences
■ The container class vector<T, Allocator>supports standard array opera-tions, such as direct access to individual objects via the subscript operator [], and quick appending and deletion at the end of the container However, the run-time for insertion and deletion at the beginning or in the middle of the container
is linear, that is, proportional to the number of objects stored in the container
■ The container class list<T, Allocator>provides functionality that is typi-cal for double linked lists This includes quick insertion and deletion at any given position General list operations, such as sorting and merging, are also defined
■ The container class deque<T, Allocator>(double ended queue, pronounced
“deck”) provides direct access via a subscript operator, just like a normal array, but offers optimized insertion and deletion at the beginning and end of the con-tainer The same operations in the middle of a container have a linear runtime The second template parameter is used for any storage allocation to be performed The
storage management is represented by a so-called allocator class, which is parameterized
by an object of type T It enables dynamic memory allocation for objects of type T The
default value of the template parameter is the standard allocator class allocator<T>
that uses the newanddeleteoperators to allocate and release memory
䊐 Adapter Classes
The basic sequence classes are used to construct so-called adapter classes An adapter class
expects a sequence as a template argument and stores the sequence in a protected
data member
The opposite page shows various adapter classes The priority_queuetemplate represents priority queues The relationship between the keys used to manage the
priori-ties is defined in the comparator class, Compare The default value of the template parameter is the predefined comparator class, less<T>, which uses the lesser than oper-ator<for type T
Trang 6754 C H A P T E R 3 3 C O N T A I N E R S
// Outputs a list containing integers
//
-#include <list>
#include <iostream>
using namespace std;
typedef list<int> INTLIST; // int list
int display(const INTLIST& c)
{ int z = 0; // Counter
list<int>::const_iterator pos; // Iterator for( pos = c.begin(); pos != c.end(); pos++, z++) cout << *pos << endl;
cout << endl;
return z;
}
// iterat_t.cpp: Outputs an array of accounts
//
-#include <vector>
#include <iostream>
using namespace std;
#include "account.h"
typedef vector<Account> AccVec; // Account vector void display(const AccVec& v)
{
AccVec::const_iterator pos; // Iterator for( pos = v.begin(); pos < v.end(); pos++) pos->display();
cout << endl;
}
■ ITERATORS
Iterating lists
Iterating vectors
Trang 7䊐 Positioning and Iterating in Containers
Each object in a container occupies the specific position where it was stored To allow you to work with the objects in a container, the positions of the objects in the container must be accessible There must therefore be at least one mechanism that allows:
■ read and/or write access to the object at any given position and
■ moving from the position of one object to the position of the next object in the container
This situation should be familiar from your experience of working with pointers Given thatiis the index of an element in an array v,(v+i)is its address, *(v+i)the array element itself, and (v + (++i))the address of the next array element
Iterators were introduced in C++ to provide a uniform model for positioning and iter-ation in containers An iterator can thus be regarded as an abstraction of a pointer
䊐 Iterator Types
Two types of iterators are important in this context:
■ bidirectional iterators, which can be shifted up by the increment operator ++
and down with the decrement operator , and use the operators *and->to provide write or read access to objects
■ random access iterators, which are bidirectional iterators that can additionally
perform random positioning The subscript operator []was overloaded for this purpose, and the operations defined for pointer arithmetic, such as addition/sub-traction of integers or comparison of iterators, are defined
The container classes vector<T>anddeque<T>have random access iterators and the container class list<T>has bidirectional iterators
䊐 Iterator Classes
The types iteratorandconst_iteratorare defined in all the above classes to rep-resent iterators An iterator belonging to one of these classes can reference constant or non-constant objects
The methods begin()andend()are also defined The begin()method accesses the first position and end()accesses the position after the last container object.
Containers that belong to adapter classes offer only restricted access to the beginning
or end You cannot use iterators to walk through them
Trang 8756 C H A P T E R 3 3 C O N T A I N E R S
// sortVec.h: The Class Template SortVec representing // a sorted vector
// -#include <vector> // For class template vector<T>
#include <functional> // For comparator class less<T> using namespace std;
template <class T, class Compare = less<T> >
class SortVec : public vector<T>
{
public:
SortVec() { } SortVec(int n, const T& x = T());
void insert(const T& obj); // in sorted order int search(const T& obj);
void merge(const SortVec<T>& v);
};
// sortv_t.cpp : Tests the template SortVec
// -#include "sortVec.h"
typedef SortVec<int> IntSortVec;
int main() {
IntSortVec v, w; // Default constructor v.insert(2);
v.insert(7); v.insert(1);
int n = v.search(7);
w.insert(3); w.insert(9);
v.merge(w);
return 0;
} // The array v then contains the elements: 1 2 3 7 9
■ DECLARING SEQUENCES
The derived container class sortVec<T, Compare>
Using the container class sortVec
Trang 9䊐 Constructors of vector, list, and deque
The container classes vector,list, and dequedefine three constructors and a copy constructor with which sequences can be created Their functionality is similar for the various classes and is discussed in the following section using the vector class as an example
The statement
Example: vector<Account> v;
declares an empty container vfor objects of the Account type You can then insert individual objects into the container
However, you can also declare a container and fill it with a predefined number of object copies
Example: Fraction x(1, 1);
vector<Fraction> cont(100, x);
This defines the container contwith 100 Fractiontype objects, and fills it with the objectx If the second argument is not supplied, each of the 100 objects is initialized by the default constructor
Finally, you can initialize a container with a part of another container To do so, you must state a range of iterators
Example: vector<double> v(first,last);
The arguments firstandlastare iterators in an existing container The new con-tainer,v,is initialized using objects in the range [first,last): this includes all the objects between the positions first(includingfirst) and last(excludinglast)
䊐 Constructors for Adapter Classes
Only a default constructor and the copy constructor are defined for adapter classes Given that waitis a predefined queue of the container class queue<double>, the fol-lowing statement
Example: queue<double> w(wait);
creates a new queue, w,and uses the object waitto initialize it
The opposite page shows the derived container class sortVec, which is used to rep-resent sorted, dynamic arrays The class is parameterized by the type Tof array elements The second template parameter is a comparator class, which represents a comparison cri-terion for sorting
Trang 10758 C H A P T E R 3 3 C O N T A I N E R S
Method Effect
void push_back(const T&x); Adds x at the end of the
sequence.
Adds x before the first element of the sequence Inserts x after position pos
and returns the position of the newly inserted element Inserts n copies of x after position pos and returns the number of inserted elements Inserts all elements from range [first,last) after position pos into the sequence.
void push_front(const T&x);
iterator insert(iterator pos, const T& x = T() );
size_type insert(iterator pos, size_type n, const T& x)
void insert(iterator pos,
InputIterator first InputIterator last)
// Method insert() adds a new object at the end // of the vector and reorganizes in ascending order
// -template <class T, class Compare >
void SortVec<T, Compare>::insert(const T& obj)
{ SortVec::iterator pos, temp;
push_back(obj); // Add at the end pos = end(); pos ; // Last position while (pos > begin()) // Sort:
{ if( obj < *pos) // Swap:
{ temp = pos; *(++temp) = *pos; *pos = obj; } else break;
} }
■ INSERTING IN SEQUENCES
Inserting methods
Method insert() of the derived container class SortVec