䊐 Associative Container Classes The opposite page shows various classes used to represent sets, multisets, maps, and mul-timaps.. Sets and multisets are used for efficient management of
Trang 1Sequences store objects in linear order Searching for a given object will thus require a linear runtime If you have only a few objects to deal with, this will not cause any signifi-cant delay However, it is a major disadvantage in large collections of objects
䊐 Representing Sets and Maps
Associative containers with different classes that represent sets and maps allow you
opti-mize runtimes They manage objects in so-called heaps, that is in trees with a minimum
height Operations are performed by sortable keys One of the characteristics of a heap is that the object with the smallest key is always stored at the top of the heap
Insertion, deletion, and search operations in sets and maps can be performed with log-arithmic runtimes That is, the response is proportional to log(n), where nis the num-ber of objects in a container Since a logarithmic function grows very slowly, response will be phenomenally quick
䊐 Unique and Ambiguous Keys
In a set, each object contains a key This is why we refer to embedded keys The relation-ship between the objects is defined by reference to this key Besides sets, which have
unique keys, you can also define multisets, where multiple objects can have the same key.
Maps are used to manage key/object pairs In other words, the key is not embedded in the object but stored separately from it The type of the key is Key,andTis the object type The relationship between the objects is again defined by the keys
Besides maps, which contain only unique keys, you can also define multimaps, where
several objects can exist for a single key
䊐 Associative Container Classes
The opposite page shows various classes used to represent sets, multisets, maps, and mul-timaps The template parameter Compareis a comparator class and Allocatoris an allocator class Both parameters have default values, which we already saw in the context
of sequences
The methods begin()andend()are defined for access to the positions in all asso-ciative container classes They return the position of the first element or the position after the last element
Trang 2770 C H A P T E R 3 3 C O N T A I N E R S
// set_t.cpp: Tests sets and multisets //
-#include <set>
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
typedef set<int> IntSet; // Define type and typedef IntSet::iterator SetIter; // iterator type
typedef multiset<int> IntMultiSet; // Multiset and typedef IntMultiSet::iterator MultiSetIter; // iterator
int main() {
IntSet lotto; // Create a set
SetIter pos; // Bidirectional iterator
srand((unsigned) time(NULL));
while( lotto.size() < 6) // Insert lotto.insert( rand()%50 );
cout << "These are your lotto numbers: " << endl; for( pos = lotto.begin(); pos != lotto.end(); pos++) cout << *pos << " ";
cout << endl << endl;
IntMultiSet ms; // Create a multiset MultiSetIter mpos; // Bidirectional iterator for( int i=0; i < 10; i++) // Insert
ms.insert( rand()%10 );
cout << "And now 10 random numbers "
<< " between 0 and 10: " << endl;
for( mpos = ms.begin(); mpos != ms.end(); mpos++) cout << *mpos << " ";
cout << endl;
return 0;
}
■ SETS AND MULTISETS
Sample sets and multisets
Trang 3Sets and multisets are used for efficient management of object collections with sortable keys, that is, insertion, deletion, and search operations can be performed with logarith-mic runtimes Keys are always parts of objects, thus, keys are data members whose rela-tionships to one another must be defined in the corresponding class A lesser than relationship is normally defined for this purpose, that is, the operator <will be over-loaded for the class
䊐 Declaring Sets and Multisets
The container classes setandmultisethave two constructors each for creating con-tainers You can use the default constructor to create sets and multisets with a length of
0 The second constructor inserts objects from a range of iterators into the new set or multiset
AccountSet mySet(first, last);
Here,[first, last)is a range of iterators in an existing container whose objects are
ofAccounttype
The copy constructor is also defined, and this allows you to use an existing container
of the same type to initialize a new container
䊐 Inserting and Deleting
Theinsert()method is available for insertions This allows for insertion of individual objects or multiple objects from a given range of iterators
In contrast to multisets, a new object is only inserted in a set if it does not already exist
in the container
You can use the erase()method to delete objects To do so, you can either specify the object itself or its position in the container
This deletes the first element in the AccountSetset
You can delete all objects in a container with the following statement:
For erasing a whole container you can also use the clear()method Calling empty() will tell you whether the container is empty The method returns the number of
Trang 4772 C H A P T E R 3 3 C O N T A I N E R S
// mulmap_t.cpp: Testing multimaps //
-#include <map>
#include <string>
#include <iostream>
using namespace std;
typedef multimap<int, string> MULTI_MAP;
typedef MULTI_MAP::iterator ITERATOR;
int main() {
MULTI_MAP m; // Create a multimap ITERATOR pos; // Iterator
// To insert:
m.insert(pair<int, string>(7, "Bob") );
m.insert(pair<int, string>(3, "Sarah"));
m.insert(pair<int, string>(1, "Diana"));
m.insert(pair<int, string>(1, "Lisa"));
cout << "This is the multimap: " << endl;
for(pos = m.begin(); pos!= m.end(); pos++) cout << pos->first << " "
<< pos->second << endl;
cout << endl;
pos = m.find(3); // Search for the pair
// with the given key 3 if( pos != m.end()) // and output the pair cout << pos->first << " " << pos->second << endl;
int key = 1; // Determine the quantity of
// pairs with key value 1: cout << "There are " << m.count(key)
<< " pairs with key " << key << endl;
return 0;
}
■ MAPS AND MULTIMAPS
Using multimaps
Trang 5䊐 Representing Pairs of Keys/Objects
Maps and multimaps store pairs of sorted keys and objects The key is used again to iden-tify the object but is stored separately from the object The comparison criterion is applied to the keys
The C++ Standard Library contains the class template pair<const Key,T>with twopublicdata members firstandsecond, a default constructor, and a copy con-structor to represent key/object pairs The first template parameter, Key, is the key type and the second is the object type T The data member firstis used to store the keys, andsecondstores the associated object
Given that posis the position of an object in a map or multimap, you can reference the key with pos->first, and the associated object itself with pos->second
䊐 Using Maps and Multimaps
The container classes mapandmultimapcontain constructors with the same function-ality as the setandmultisetclasses Thus, you can create a container with a length
of0, or use the objects in an existing container to initialize a new container The copy constructor is also defined
The methods insert()for insertion, and erase()andclear()for deletion have the same interfaces as in the container classes set and multiset The methods size(), which you can use to discover the length of the container, and empty(), which ascertains whether the container is empty, are also defined
Thefind()method is used to look up key/object pairs and expects a key as an argu-ment in the mapandmultimapclasses Its return value is the associated position in the container In the case of multimaps where several objects can have the same key, it returns the first position with that key If the search fails, the value end()is returned as
a pseudo position
You can use the count()method to discover the number of key/object pairs with a given key in the container The method expects a key as an argument The method returns0or1for maps, depending on whether a pair exists or not In the case of multi-maps, the return value can be greater than 1, of course
Trang 6774 C H A P T E R 3 3 C O N T A I N E R S
// bitmap.h : Defines the template Bitmap<N>
// representing raster images
//
-#ifndef _BITMAP_
#define _BITMAP_
#include <bitset>
#include <stdexcept>
using namespace std;
template <int N>
class Bitmap : public bitset<N>
{ private:
int lines, cols; // Number of rows and columns int ax, ay; // Current cursor position int ai; // Current index in the bitset public:
Bitmap(int l, int c);
void move(int x, int y);
void draw(int x, int y);
};
template <int N>
Bitmap<N>::Bitmap(int l, int c) {
if (l*c <= N) {
reset(); // Set all bits to 0 lines = l; cols = c; // Rows and columns
ax = 0; ay = 0; ai = 0; // Current position }
else throw invalid_argument("Invalid argument \n"); }
template <int N>
void Bitmap<N>::move(int x, int y) {
if( x >= 0 && x < lines && y >= 0 && y < cols) { ax = x; ay = y; ai = x * cols + y; } else throw invalid_argument("Invalid argument\n"); }
// to be continued
■ BITSETS
Representing raster images with bitmaps
Trang 7䊐 Declaring Bitsets
A bitset stores a bit sequence of a given length This allows storage of mass bit coded data, such as raster images, with minimum memory used
The container class bitset<N>provides the functionality needed to manage bitsets The template parameter Nis the length of bitset, that is the maximum number of bits stored
You can use the default constructor to create a bitset with no initial values However, you can also use a given bit-pattern to initialize a bitset The bit-pattern is either defined
as an unsigned longvalue or as a string
bitset<1024> b(s);
The string scan contain only the '0'or'1'characters The last character in the string will be the first bit value (that is 0 or 1) at bit position 0, the second to last character in the string is the bit value at position 1, and so on The remaining bits are padded with 0
up to a length of N This also applies when an unsigned longvalue is used for initial-ization purposes
䊐 Notes on the Sample Program Opposite
The container class Bitmap<N>, which is defined opposite, can be used to represent
simple monochrome raster images A pixel (picture element) is represented by a bit in a
bitset If the bit is set, a pixel on screen will be illuminated (white) and otherwise turned off (black)
The number of pixels that can be represented horizontally and vertically is defined by the resolution 480 by 800 is a typical screen resolution and 3300 by 2300 is a typical res-olution for laser printers (at 300 dpi) for an 81⁄2⫻ 11 page size The value of Nis the product of the number of pixels in horizontal and vertical direction
The container class Bitmap<N> is derived from bitset<N> by public inheri-tance Thus, the class comprises a bitset and all the publicbitset management methods
it inherits Additional data members are used to store the number of rows and columns of pixels, the current cursor position, and the current bitset index The move()method moves the cursor to the position with the given coordinates The draw()method draws
a straight line from the current cursor position to the point with the given coordinates
Trang 8776 C H A P T E R 3 3 C O N T A I N E R S
// bitmap.h: In addition the Bresenham algorithm
// -template <int N>
void Bitmap<N>::draw(int x, int y) {
if( x >= 0 && x < lines && y >= 0 && y < cols) {
int savex = x, savey = y;
if(ax > x) // Draw in ascending x-direction { // => possibly swap (ax,ay) and (x,y) int temp = ax; ax = x; x = temp;
temp = ay; ay = y; y = temp;
} int dx = x - ax, dy = y - ay;
int xinc = 1, yinc; // Increment
if( dy < 0) // Gradient < 0 ? { yinc = -1; dy = -dy;} // Decrement y else yinc = 1; // or else increment
int count = dx + dy; // Number of pixels to be set
int d = (dx - dy)/2; // Measurement of deviation
// off the line
while( count > 0) {
ai = ax * cols + ay; // Index in the bitset set(ai); // Set the bit
if( d < 0) // Next pixel in { ay += yinc; d += dx; } // y-direction else // or else in { ax += xinc; d -= dy; } // x-direction }
ax = savex; ay = savey; // Current cursor position
ai = ax * cols + ay; // Current index in bitset }
else throw invalid_argument("Invalid argument\n"); }
#endif
■ BITSETS (CONTINUED)
Bresenham algorithm
Trang 9䊐 Manipulating Bits
The container class Bitset<N>provides the get()andset()methods for reading and writing individual bits These methods expect a bit position as an argument You can additionally pass a value of 0or1to the setmethod, which writes this value at the bit position stated The default value here is 1
If you call the set()method without any arguments, all the bits in the bitset are set
to 1 In contrast, the reset()method deletes all the bits Bits can be inverted by a call
to the flip()method Each 0-bit in the bitset is set then to 1and each 1-bit is set to
0
Bits at specific coordinates can be referenced by the subscript operator The index is a bit position, that is a number between 0andN-1
As you would expect, bitwise operators can also be used for bit manipulation The bit operators&,|, and ^are globally overloaded for bitsets The operator functions for the NOT operator ~, the shift operators <<and>>, and the operators for compound assign-ments,&=,|=,^=, are implemented as methods of the container class
䊐 The Bresenham Algorithm
The opposite page shows the draw()method that draws a line from the current cursor position pixel by pixel to the given coordinates The Bresenham algorithm used here applies incremental techniques Starting at the current cursor position, it sets the neigh-boring pixel in the x- or y-direction To do this, you only need to increment or decre-ment the x- or y-coordinate by 1 This avoids time consuming floating-point arithmetic, which would be required to solve a linear equation
To allow drawing to take place along a positive x-axis, the starting and target points
of the straight line can be swapped The difference between the y-coordinates of the starting and target points dy = y - aythen determines whether to increment or decrement by 1 along the y-direction
Drawing neighboring pixels creates a “staircase” effect, which deviates from the straight line The variable d = (dx - dy)/2represents this deviation If the value of
dis negative, the line is seen to be growing along y-direction and the next pixel is drawn along the y-direction Then the deviation is corrected by adding dx As soon as d becomes positive, the next pixel is drawn along the x-direction and the deviation is cor-rected with dy
Trang 10778 C H A P T E R 3 3 C O N T A I N E R S
9 queues have been created
The queues will now be filled using the hot potato algorithm
Some elements of randomly selected queues are removed
Output the queues:
1.queue: 28 88 70 60 6 2.queue: 64 6 54 1 3.queue: 2 88 64 30 66 29 11 74 49 41 4.queue: 17 25
5.queue: 96 97 47 27 71 34 87 58 6.queue: 77 82 54
7.queue: 35 65 23 40 5 83 92 8.queue: 32 23 54
9.queue: 28 55 54 73 28 82 21 99
1 Queue
2 Queue
3 Queue
4 Queue Entrance
■ EXERCISE
Hot potato algorithm
Test output