thinking in c 2nd ed volume 2 rev 20 - phần 6 doc

52 245 0
thinking in c 2nd ed volume 2 rev 20 - phần 6 doc

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

261 z 516 Because of the genericity of the STL, the concept of removal is a bit constrained. Since elements can only be “removed” via iterators, and iterators can point to arrays, vectors, lists, and so on, it is not safe or reasonable to actually try to destroy the elements that are being removed and to change the size of the input range [first, last). (An array, for example, cannot have its size changed.) So instead, what the STL “remove” functions do is rearrange the sequence so that the “removed” elements are at the end of the sequence, and the “un-removed” elements are at the beginning of the sequence (in the same order that they were before, minus the removed elements—that is, this is a stable operation). Then the function will return an iterator to the “new last” element of the sequence, which is the end of the sequence without the removed elements and the beginning of the sequence of the removed elements. In other words, if new_last is the iterator that is returned from the “remove” function, [first, new_last) is the sequence without any of the removed elements, and [new_last, last) is the sequence of removed elements. If you are simply using your sequence, including the removed elements, with more STL algorithms, you can just use new_last as the new past-the-end iterator. However, if you’re using a resizable container c (not an array) and you actually want to eliminate the removed elements from the container, you can use erase( ) to do so, for example: Comment c.erase(remove(c.begin(), c.end(), value), c.end()); You can also use the resize( ) member function that belongs to all standard sequences (more on this in the next chapter). Comment The return value of remove( ) is the new_last iterator, so erase( ) deletes all the removed elements from c. The iterators in [new_last, last) are dereferenceable, but the element values are unspecified and should not be used. ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred); OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred); Comment Each of the “remove” forms moves through the range [first, last), finding values that match a removal criterion and copying the unremoved elements over the removed elements (thus effectively removing them). The original order of the unremoved elements is maintained. The return value is an iterator pointing past the end of the range that contains none of the removed elements. The values that this iterator points to are unspecified. The “if” versions pass each element to pred( ) to determine whether it should be removed. (If pred( ) returns true, the element is removed.) The “copy” versions do not modify the original sequence, but instead copy the unremoved values into a range beginning at result and return an iterator indicating the past-the-end value of this new range. ForwardIterator unique(ForwardIterator first, ForwardIterator last); ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred); OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result); OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred); Comment Each of the “unique” functions moves through the range [first, last), finding adjacent values that are equivalent (that is, duplicates) and “removing” the duplicate elements by copying over them. The original order of the unremoved elements is maintained. The return value is an iterator 262 z 516 pointing past the end of the range that has the adjacent duplicates removed. Because only duplicates that are adjacent are removed, it’s likely that you’ll want to call sort( ) before calling a “unique” algorithm, since that will guarantee that all the duplicates are removed. For each iterator value i in the input range, the versions containing binary_pred call: Comment binary_pred(*i, *(i-1)); and if the result is true, *i is considered a duplicate. The “copy” versions do not modify the original sequence, but instead copy the unremoved values into a range beginning at result and return an iterator indicating the past-the-end value of this new range. Example This example gives a visual demonstration of the way the “remove” and “unique” functions work. //: C06:Removing.cpp // The removing algorithms #include <algorithm> #include <cctype> #include <string> #include "Generators.h" #include "PrintSequence.h" using namespace std; struct IsUpper { bool operator()(char c) { return isupper(c); } }; int main() { string v; v.resize(25); generate(v.begin(), v.end(), CharGen()); print(v.begin(), v.end(), "v original", ""); // Create a set of the characters in v: string us(v.begin(), v.end()); sort(us.begin(), us.end()); string::iterator it = us.begin(), cit = v.end(), uend = unique(us.begin(), us.end()); // Step through and remove everything: while(it != uend) { cit = remove(v.begin(), cit, *it); print(v.begin(), v.end(), "Complete v", ""); print(v.begin(), cit, "Pseudo v ", " "); cout << "Removed element:\t" << *it << "\nPsuedo Last Element:\t" << *cit << endl << endl; it++; } generate(v.begin(), v.end(), CharGen()); print(v.begin(), v.end(), "v", ""); cit = remove_if(v.begin(), v.end(), IsUpper()); print(v.begin(), cit, "v after remove_if IsUpper", " "); // Copying versions are not shown for remove // and remove_if. sort(v.begin(), cit); 263 z 516 print(v.begin(), cit, "sorted", " "); string v2; v2.resize(cit - v.begin()); unique_copy(v.begin(), cit, v2.begin()); print(v2.begin(), v2.end(), "unique_copy", " "); // Same behavior: cit = unique(v.begin(), cit, equal_to<char>()); print(v.begin(), cit, "unique equal_to<char>", " "); } ///:~ The string v, which is a container of characters, as you know, is filled with randomly generated characters. Each character is used in a remove statement, but the entire string v is printed out each time so you can see what happens to the rest of the range, after the resulting endpoint (which is stored in cit). To demonstrate remove_if( ), the address of the standard C library function isupper( ) (in <cctype> is called inside the function object class IsUpper, an object of which is passed as the predicate for remove_if( ). This returns true only if a character is uppercase, so only lowercase characters will remain. Here, the end of the range is used in the call to print( ) so only the remaining elements will appear. The copying versions of remove( ) and remove_if( ) are not shown because they are a simple variation on the noncopying versions, which you should be able to use without an example. The range of lowercase letters is sorted in preparation for testing the “unique” functions. (The “unique” functions are not undefined if the range isn’t sorted, but it’s probably not what you want.) First, unique_copy( ) puts the unique elements into a new vector using the default element comparison, and then the form of unique( ) that takes a predicate is used; the predicate used is the built-in function object equal_to( ), which produces the same results as the default element comparison. Sorting and operations on sorted ranges A significant category of STL algorithms requires that the range they operate on be in sorted order. STL provides a number of separate sorting algorithms, depending on whether the sort should be stable, partial, or just regular (non-stable). Oddly enough, only the partial sort has a copying version; otherwise you’ll need to make your own copy before sorting if that’s what you want. Comment Once your sequence is sorted, you can perform many operations on that sequence, from simply locating an element or group of elements to merging with another sorted sequence or manipulating sequences as mathematical sets. Each algorithm involved with sorting or operations on sorted sequences has two versions. The first uses the object’s own operator< to perform the comparison, and the second uses operator ( )(a, b) to determine the relative order of a and b. Other than this, there are no differences, so this distinction will not be pointed out in the description of each algorithm. Sorting The sort algorithms require ranges delimited by random-access iterators, such as a vector or deque. The list container has its own built-in sort( ) function, since it only supports bi- directional iteration. Comment void sort(RandomAccessIterator first, RandomAccessIterator last); void sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred); Comment 264 z 516 Sorts [first, last) into ascending order. The first form uses operator< and the second form uses the supplied comparator object to determine the order. void stable_sort(RandomAccessIterator first, RandomAccessIterator last); void stable_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred); Comment Sorts [first, last) into ascending order, preserving the original ordering of equivalent elements. (This is important if elements can be equivalent but not identical.) Comment void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, StrictWeakOrdering binary_pred); Comment Sorts the number of elements from [first, last) that can be placed in the range [first, middle). The rest of the elements end up in [middle, last) and have no guaranteed order. Comment RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, StrictWeakOrdering binary_pred); Comment Sorts the number of elements from [first, last) that can be placed in the range [result_first, result_last) and copies those elements into [result_first, result_last). If the range [first, last) is smaller than [result_first, result_last), the smaller number of elements is used. Comment void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, StrictWeakOrdering binary_pred); Comment Just like partial_sort( ), nth_element( ) partially orders a range of elements. However, it’s much “less ordered” than partial_sort( ). The only thing that nth_element( ) guarantees is that whatever location you choose will become a dividing point. All the elements in the range [first, nth) will pair-wise satisfy the binary predicate (operator< by default, as usual), and all the elements in the range (nth, last] will not. However, neither subrange is in any particular order, unlike partial_sort( ) which has the first range in sorted order. If all you need is this very weak ordering (if, for example, you’re determining medians, percentiles, and that sort of thing), this algorithm is faster than partial_sort( ). Locating elements in sorted ranges Once a range is sorted, you can use a group of operations to find elements within those ranges. In the following functions, there are always two forms. One assumes the intrinsic operator< performs the sort, and the second operator must be used if some other comparison function object performs the sort. You must use the same comparison for locating elements as you do to perform the sort; otherwise, the results are undefined. In addition, if you try to use these functions on unsorted ranges, the results will be undefined. bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering binary_pred); Tells you whether value appears in the sorted range [first, last). 265 z 516 ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering binary_pred); Comment Returns an iterator indicating the first occurrence of value in the sorted range [first, last). If value is not present, an iterator to where it would fit in the sequence is returned. Comment ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering binary_pred); Comment Returns an iterator indicating one past the last occurrence of value in the sorted range [first, last). If value is not present, an iterator to where it would fit in the sequence is returned. pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value); pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering binary_pred); Comment Essentially combines lower_bound( ) and upper_bound( ) to return a pair indicating the first and one-past-the-last occurrences of value in the sorted range [first, last). Both iterators indicate the location where value would fit if it is not found. You may find it surprising that the binary search algorithms take a forward iterator instead of a random access iterator. (Most explanations of binary search use indexing.) Remember that a random access iterator “is-a” forward iterator, and can be used wherever the latter is specified. If the iterator passed to one of these algorithms in fact supports random access, then the efficient logarithmic-time procedure is used, otherwise a linear search is performed. Example The following example turns each input word into an NString and added to a vector<NString>. The vector is then used to demonstrate the various sorting and searching algorithms. Comment //: C06:SortedSearchTest.cpp // Test searching in sorted ranges #include <algorithm> #include <cassert> #include <ctime> #include <cstdlib> #include <cstddef> #include <fstream> #include <iostream> #include <iterator> #include <vector> #include "NString.h" #include "PrintSequence.h" #include " /require.h" using namespace std; int main(int argc, char* argv[]) { typedef vector<NString>::iterator sit; char* fname = "test.txt"; if(argc > 1) fname = argv[1]; ifstream in(fname); [88] 266 z 516 assure(in, fname); srand(time(0)); cout.setf(ios::boolalpha); vector<NString> original; copy(istream_iterator<string>(in), istream_iterator<string>(), back_inserter(original)); require(original.size() >= 4, "Must have four elements"); vector<NString> v(original.begin(), original.end()), w(original.size() / 2); sort(v.begin(), v.end()); print(v.begin(), v.end(), "sort"); v = original; stable_sort(v.begin(), v.end()); print(v.begin(), v.end(), "stable_sort"); v = original; sit it = v.begin(), it2; // Move iterator to middle for(size_t i = 0; i < v.size() / 2; i++) it++; partial_sort(v.begin(), it, v.end()); cout << "middle = " << *it << endl; print(v.begin(), v.end(), "partial_sort"); v = original; // Move iterator to a quarter position it = v.begin(); for(size_t i = 0; i < v.size() / 4; i++) it++; // Less elements to copy from than to the destination partial_sort_copy(v.begin(), it, w.begin(), w.end()); print(w.begin(), w.end(), "partial_sort_copy"); // Not enough room in destination partial_sort_copy(v.begin(), v.end(), w.begin(), w.end()); print(w.begin(), w.end(), "w partial_sort_copy"); // v remains the same through all this process assert(v == original); nth_element(v.begin(), it, v.end()); cout << "The nth_element = " << *it << endl; print(v.begin(), v.end(), "nth_element"); string f = original[rand() % original.size()]; cout << "binary search: " << binary_search(v.begin(), v.end(), f) << endl; sort(v.begin(), v.end()); it = lower_bound(v.begin(), v.end(), f); it2 = upper_bound(v.begin(), v.end(), f); print(it, it2, "found range"); pair<sit, sit> ip = equal_range(v.begin(), v.end(), f); print(ip.first, ip.second, "equal_range"); } ///:~ This example uses the NString class seen earlier, which stores an occurrence number with copies of a string. The call to stable_sort( ) shows how the original order for objects with equal strings is preserved. You can also see what happens during a partial sort (the remaining unsorted elements are in no particular order). There is no “partial stable sort.” Comment Notice in the call to nth_element( ) that, whatever the nth element turns out to be (which will vary from one run to another because of URandGen), the elements before that are less, 267 z 516 and after that are greater, but the elements have no particular order other than that. Because of URandGen, there are no duplicates, but if you use a generator that allows duplicates, you’ll see that the elements before the nth element will be less than or equal to the nth element. This example also illustrates all three binary search algorithms. As advertised, lower_bound ( ) refers to the first element in the sequence equal to a given key, upper_bound( ) points one past the last, and equal_range( ) returns both results as a pair. Comment Merging sorted ranges As before, the first form of each function assumes the intrinsic operator< performs the sort. The second form must be used if some other comparison function object performs the sort. You must use the same comparison for locating elements as you do to perform the sort; otherwise, the results are undefined. In addition, if you try to use these functions on unsorted ranges, the results will be undefined. OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred); Comment Copies elements from [first1, last1) and [first2, last2) into result, such that the resulting range is sorted in ascending order. This is a stable operation. void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, StrictWeakOrdering binary_pred); Comment This assumes that [first, middle) and [middle, last) are each sorted ranges in the same sequence. The two ranges are merged so that the resulting range [first, last) contains the combined ranges in sorted order. Comment Example It’s easier to see what goes on with merging if ints are used; the following example also emphasizes how the algorithms (and our own print template) work with arrays as well as containers. Comment //: C06:MergeTest.cpp // Test merging in sorted ranges #include <algorithm> #include "PrintSequence.h" #include "Generators.h" using namespace std; int main() { const int sz = 15; int a[sz*2] = {0}; // Both ranges go in the same array: generate(a, a + sz, SkipGen(0, 2)); a[3] = 4; a[4] = 4; generate(a + sz, a + sz*2, SkipGen(1, 3)); print(a, a + sz, "range1", " "); print(a + sz, a + sz*2, "range2", " "); int b[sz*2] = {0}; // Initialize all to zero merge(a, a + sz, a + sz, a + sz*2, b); print(b, b + sz*2, "merge", " "); 268 z 516 // Reset b for(int i = 0; i < sz*2; i++) b[i] = 0; inplace_merge(a, a + sz, a + sz*2); print(a, a + sz*2, "inplace_merge", " "); int* end = set_union(a, a + sz, a + sz, a + sz*2, b); print(b, end, "set_union", " "); } ///:~ In main( ), instead of creating two separate arrays, both ranges are created end to end in the same array a. (This will come in handy for the inplace_merge.) The first call to merge( ) places the result in a different array, b. For comparison, set_union( ) is also called, which has the same signature and similar behavior, except that it removes duplicates from the second set. Finally, inplace_merge( ) combines both parts of a. Comment Set operations on sorted ranges Once ranges have been sorted, you can perform mathematical set operations on them. bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, StrictWeakOrdering binary_pred); Comment Returns true if [first2, last2) is a subset of [first1, last1). Neither range is required to hold only unique elements, but if [first2, last2) holds n elements of a particular value, [first1, last1) must also hold at least n elements if the result is to be true. OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred); Comment Creates the mathematical union of two sorted ranges in the result range, returning the end of the output range. Neither input range is required to hold only unique elements, but if a particular value appears multiple times in both input sets, the resulting set will contain the larger number of identical values. OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred); Comment Produces, in result, the intersection of the two input sets, returning the end of the output range—that is, the set of values that appear in both input sets. Neither input range is required to hold only unique elements, but if a particular value appears multiple times in both input sets, the resulting set will contain the smaller number of identical values. OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred); Comment Produces, in result, the mathematical set difference, returning the end of the output range. All the elements that are in [first1, last1) but not in [first2, last2) are placed in the result set. Neither input range is required to hold only unique elements, but if a particular value appears multiple times in both input sets (n times in set 1 and m times in set 2), the resulting set will contain max(n-m, 0) copies of that value. 269 z 516 OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred); Comment Constructs, in result, the set containing: Comment 1. All the elements in set 1 that are not in set 2 2. All the elements in set 2 that are not in set 1. Neither input range is required to hold only unique elements, but if a particular value appears multiple times in both input sets (n times in set 1 and m times in set 2), the resulting set will contain abs(n-m) copies of that value, in which abs( ) is the absolute value. The return value is the end of the output range. Example It’s easiest to see the set operations demonstrated using simple vectors of characters, so you view the sets more easily. These characters are randomly generated and then sorted, but the duplicates are not removed so you can see what the set operations do when duplicates are involved. //: C06:SetOperations.cpp // Set operations on sorted ranges #include <vector> #include <algorithm> #include "PrintSequence.h" #include "Generators.h" using namespace std; int main() { const int sz = 30; char v[sz + 1], v2[sz + 1]; CharGen g; generate(v, v + sz, g); generate(v2, v2 + sz, g); sort(v, v + sz); sort(v2, v2 + sz); print(v, v + sz, "v", ""); print(v2, v2 + sz, "v2", ""); bool b = includes(v, v + sz, v + sz/2, v + sz); cout.setf(ios::boolalpha); cout << "includes: " << b << endl; char v3[sz*2 + 1], *end; end = set_union(v, v + sz, v2, v2 + sz, v3); print(v3, end, "set_union", ""); end = set_intersection(v, v + sz, v2, v2 + sz, v3); print(v3, end, "set_intersection", ""); end = set_difference(v, v + sz, v2, v2 + sz, v3); print(v3, end, "set_difference", ""); end = set_symmetric_difference(v, v + sz, v2, v2 + sz, v3); print(v3, end, "set_symmetric_difference",""); } ///:~ After v and v2 are generated, sorted, and printed, the includes( ) algorithm is tested by seeing if the entire range of v contains the last half of v, which of course it does; so the result 270 z 516 should always be true. The array v3 holds the output of set_union( ), set_intersection( ), set_difference( ), and set_symmetric_difference( ), and the results of each are displayed so you can ponder them and convince yourself that the algorithms do indeed work as promised. Comment Heap operations A heap is an array-like data structure used to implement a “priority queue”, which is just a range that is organized in a way that accommodates retrieving elements by priority according to some comparison function. The heap operations in the standard library allow a sequence to be treated as a “heap” data structure, which always efficiently returns the element of highest priority, without fully ordering the entire sequence. Comment As with the “sort” operations, there are two versions of each function. The first uses the object’s own operator< to perform the comparison; the second uses an additional StrictWeakOrdering object’s operator( )(a, b) to compare two objects for a < b. Comment void make_heap(RandomAccessIterator first, RandomAccessIterator last); void make_heap(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred); Comment Turns an arbitrary range into a heap. Comment void push_heap(RandomAccessIterator first, RandomAccessIterator last); void push_heap(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred); Comment Adds the element *(last-1) to the heap determined by the range [first, last-1). In other words, it places the last element in its proper location in the heap. void pop_heap(RandomAccessIterator first, RandomAccessIterator last); void pop_heap(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred); Comment Places the largest element (which is actually in *first, before the operation, because of the way heaps are defined) into the position *(last-1) and reorganizes the remaining range so that it’s still in heap order. If you simply grabbed *first, the next element would not be the next-largest element; so you must use pop_heap( ) if you want to maintain the heap in its proper priority-queue order. void sort_heap(RandomAccessIterator first, RandomAccessIterator last); void sort_heap(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred); Comment This could be thought of as the complement of make_heap( ). It takes a range that is in heap order and turns it into ordinary sorted order, so it is no longer a heap. That means that if you call sort_heap( ), you can no longer use push_heap( ) or pop_heap( ) on that range. (Rather, you can use those functions, but they won’t do anything sensible.) This is not a stable sort. Applying an operation to each element in a range These algorithms move through the entire range and perform an operation on each element. They differ in what they do with the results of that operation: for_each( ) discards the return value of the operation, and transform( ) places the results of each operation into a destination sequence (which can be the original sequence). [...]... #define COUNTED_H #include #include class Counted { static int count; char* ident; public: Counted(char* id) : ident(id) { count++; } 27 2 z 5 16 ~Counted() { std::cout . main() { CountedVector cv("one"); transform(cv.begin(), cv.end(), cv.begin(), deleteP<Counted>); CountedVector cv2("two"); transform(cv2.begin(), cv2.end(), cv2.begin(), . "Inventory.h" #include "PrintSequence.h" #include <vector> #include <algorithm> using namespace std; // To calculate inventory totals: 27 5 z 5 16 class InvAccum { int quantity; int. sorted ranges #include <algorithm> #include <cassert> #include <ctime> #include <cstdlib> #include <cstddef> #include <fstream> #include <iostream> #include

Ngày đăng: 13/08/2014, 09:20

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan