| | | | / 17 \ / 23 \ | 4 | | 11 17| \_______/
17 | | v | | | | | | | | / \ =====> / \ / \ / \ | 4 | | 4 | | | | 17 | \_______/ \_______/
| | 4 | | | ^ | | | / | \ =====> / \ / | \ / \ | 4--| | | | | 17 | | 17 | \_______/ \_______/
| | | | / * \ / * \ =====> 5 | * | | * * | \_______/
| | | | / \ / \ =====> Yes | | | | \_______/ | | | | / * \ / * \ =====> No | * | | * * | \_______/
|***| |***| /*****\ /*******\ =====> Yes |*********| |*********| \-------/ | | | | / * \ / * \ =====> No | * | | * * | \_______/
The specifications for the bag operations can be found in the file bag.h.
The details of how some of the bag operations are specified can be found in the these postscript slides of Main & Savitch.
Some reminders about C++ member functions:
bool Bag::isEmpty() constindicates that the isEmpty member function of the Bag class does not modify the contents of the bag. It is like a static postcondition - a guarantee that after the function is called the state of the Bag will not have changed (static because the compiler can check it).
bool Bag::operator==(const Bag& operand) const (1) (2) (3)(1), the keyword operator indicates operator overloading - the == operator will have a user-supplied meaning rather than the standard compiler meaning (if there is such a one). (2), the keyword const indicates that the operand, supplied to the function as an argument, will not be modified by the function - it is also like a static postcondition. (3) The & in Bag& indicates that the argument will be passed by reference (the address of operand will be passed) rather than by value (a copy of operand will be passed).
friend ostream& operator <<(ostream&, const Bag&) (1) (2) (2)(1), the keyword friend indicates that the function is not a member of the class (in this case the Bag class), but the function still has access to the class' private members. It is not crucial that a user (as opposed to implementer) know a function is a friend - since the user need not know which members are private. (2) ostream is a class defined in the standard C++ library iostream.h for referring to output devices.
static const size_t CAPACITY = 20; (1) (2) (3)(1) The keyword static indicates that all bags have the same CAPACITY. (2) The keyword const indicates that CAPACITY cannot change during program execution. (3) The type size_t is defined in the C++ standard library stdlib.h. It is an unsigned (non-negative) integer that is designed for describing how many objects are stored in memory. Since size_t is an unsigned type, beware of the following situation:
size_t i; i = 0; i--; // i = i - 1 // i is not -1, but instead a large positive int // this is usually BAD
The details of how some of the bag operations are implemented can also be found in the these postscript slides of Main & Savitch.
Other details are discussed below.
int Bag::grab() { int x; size_t i; i = rand() % count; // i will be in range 0<=i<count x = data[i]; count--; for(size_t j = i; j < count; j++) data[j] = data[j+1]; return x; }
An example of calling Bag::grab(). Consider the Bag represented as:
8 4 17 33 4 11 16
If the random int i is chosen to be 0 then the resulting array is:
4 17 33 4 11 16
Meaning that roughly count number of items of the data array had to be `slid over'. This makes grab slow for large Bags. (Slower than necessary - in fact, it is O(n) - see the notes on computational complexity.)
int Bag::grab() { int x; size_t i; i = rand() % count; x = data[i]; count--; data[i] = data[count]; return x; }The algorithm has a constant running time - it performs the same number of operations regardless of how many items in are in the bag.
We would like to be able to formalize the notion that one algorithm is more efficient than another. This motivates our next topic: computational complexity.
Can we do better? Yes. We can make arrays B,C of the size of the two bags and sort b.data into B and c.data into C. Then b==c if and only if B and C have the same elements in the same order.
How fast is this version of bag equality? 2 sorting operations plus a walk through arrays B, C (which is O(n)), so the complexity it 2*sort-time + O(n). In general, sorting is worse than O(n) so, asymptotically, worst-case time is proportional to the sorting complexity.
For selection sort, bag equality would be O(n2 ) again. However, there are O(n*lg(n)) sorting algorithms (which we will learn about later in the semester). In the case of the faster sorting, bag equality can be done in O(n*lg(n)).
Drawbacks to the sorting method of bag equality include the memory overhead for the additional arrays and that for small bags this may actually be slower.