Question1:
A bag can contain more than one copy of an item. For example, the chapter describes a bag that contains the number 4 and two copies of the number 8. This bag behavior is different from a set, which can contain only a single copy of any given item. Write a new container class called set, which is similar to a bag, except that a set can contain only one copy of any given item. You’ll need to change the interface a bit. For example, instead of the bag’s count function, you’ll want a constant member function such as this:
bool set::contains
(const value_type& target) const;
// Postcondition: The return value is true if
// target is in the set; otherwise the return
// value is false.
Make an explicit statement of the invariant of the set class. Do a time analysis for each operation. At this point, an efficient implementation is not needed. For example, just adding a new item to a set will take linear time because you’ll need to check that the new item isn’t already present. Later we’ll explore more efficient implementations (including the implementation of set in the C++ Standard Library).
You may also want to add additional operations to your set class, such as an operator for subtraction.
My answer:
根据bag修改,去除了原先的erase,将原先的erase_one改成erase。
+=操作符增加一步去重操作,为了方便这一步操作,没有去除原先的count函数。
增加了contains操作。
my_set.h
#ifndef MAIN_SAVITCH_set1_H
#define MAIN_SAVITCH_set1_H
#include <cstdlib> // Provides size_t
namespace main_savitch_3
{
class set
{
public:
// TYPEDEFS and MEMBER CONSTANTS
typedef int value_type;
typedef std::size_t size_type;
static const size_type CAPACITY = 30;
// CONSTRUCTOR
set( ) { used = 0; }
// MODIFICATION MEMBER FUNCTIONS
bool erase(const value_type& target);
void insert(const value_type& entry);
void operator +=(const set& addend);
void operator -=(const set& subend);
// CONSTANT MEMBER FUNCTIONS
size_type size( ) const { return used; }
size_type count(const value_type& target) const;
bool contains(const value_type& target) const;
private:
value_type data[CAPACITY]; // The array to store items
size_type used; // How much of array is used
};
// NONMEMBER FUNCTIONS for the set class
set operator +(const set& b1, const set& b2);
set operator -(const set& b1, const set& b2);
}
#endif
my_set.cpp
#include <iostream>
#include <algorithm> // Provides copy function
#include <cassert> // Provides assert function
#include "my_set.h"
using namespace std;
namespace main_savitch_3
{
const set::size_type set::CAPACITY;
bool set::erase(const value_type& target)
{
size_type index; // The location of target in the data array
// First, set index to the location of target in the data array,
// which could be as small as 0 or as large as used-1. If target is not
// in the array, then index will be set equal to used.
index = 0;
while ((index < used) && (data[index] != target))
++index;
if (index == used)
return false; // target isn’t in the set, so no work to do.
// When execution reaches here, target is in the set at data[index].
// So, reduce used by 1 and copy the last item onto data[index].
--used;
data[index] = data[used];
return true;
}
void set::insert(const value_type& entry)
// Library facilities used: cassert
{
assert(size( ) < CAPACITY);
if(contains(entry)){
cout << entry << " already exists." << endl;
}
data[used] = entry;
++used;
}
void set::operator +=(const set& addend)
// Library facilities used: algorithm, cassert
{
assert(size( ) + addend.size( ) <= CAPACITY);
copy(addend.data, addend.data + addend.used, data + used);
used += addend.used;
for(int i = 0; i < used; i++){
while(count(data[i]) > 1){
erase(data[i]);
}
}
}
void set::operator -=(const set& subend){
// assert(size() - subend.size() >= 0);
for(size_type i = 0; i < subend.used; i++){
for(size_type j = 0; j < this->used; j++){
if(subend.data[i] == this->data[j]){
this->erase(subend.data[i]);
continue;
}
}
}
}
set::size_type set::count(const value_type& target) const
{
size_type answer;
size_type i;
answer = 0;
for (i = 0; i < used; ++i)
if (target == data[i])
++answer;
return answer;
}
set operator +(const set& b1, const set& b2)
// Library facilities used: cassert
{
set answer;
assert(b1.size( ) + b2.size( ) <= set::CAPACITY);
answer += b1;
answer += b2;
return answer;
}
set operator -(const set& b1, const set& b2){
set answer;
// assert(b1.size() - b2.size() >= 0);
answer = b1;
answer -= b2;
return answer;
}
bool set::contains(const value_type& target) const{
for(int i = 0; i < used; i++){
if(data[i] == target){
return true;
}
}
return false;
}
}
main.cpp
#include <iostream>
#include "my_set.h"
#include <string>
using namespace std;
int main(){
string girl = "Anna";
// prepare to test
main_savitch_3::set set1;// 现在是空的
cout << "Declare a new set called set1." << endl;
cout << "Keep inserting new items into set1 until it is full." << endl;
for(int i = 0; i < set1.CAPACITY; i++){
set1.insert(i);
cout << "Now there are " << set1.size() << " item(s) in set1." << endl;
}
cout << "Erase one item from set1." << endl;
if(set1.erase(28) == true){
cout << "Succeed to erase 28 from set1" << endl;
} else {
cout << "Failed to erase 28 from set1" << endl;
}
if(set1.contains(28)){
cout << "28 in set1." << endl;
} else {
cout << "no 28 in set1." << endl;
}
cout << "Now there are " << set1.size() << " item(s) in set1." << endl;
cout << "Declare set2" << endl;
main_savitch_3::set set2;
cout << "Insert 2 into set2" << endl;
set2.insert(2);
cout << "set2 = set1 + set2" << endl;
set2 += set1;
cout << "How many 2s in set2?" << endl;
cout << "Here are " << set2.count(2) << " 2(s)" << endl;
cout << "Try to erase 2 from set2." << endl;
cout << "Erase " << set2.erase(2) << " 2(s) from set2" << endl;
cout << "How many 2s in set2 now?" << endl;
cout << "Here are " << set2.count(2) << " 2(s)" << endl;
cout << "How many item(s) in set2 now?" << endl;
cout << "Here are " << set2.size() << " item(s) in set2 now." << endl;
cout << "set3 = set1 - set2" << endl;
main_savitch_3::set set3 = set1 - set2;
cout << "The size of set3: " << set3.size() << endl;
return 0;
}
结果:
Declare a new set called set1.
Keep inserting new items into set1 until it is full.
Now there are 1 item(s) in set1.
Now there are 2 item(s) in set1.
Now there are 3 item(s) in set1.
Now there are 4 item(s) in set1.
Now there are 5 item(s) in set1.
Now there are 6 item(s) in set1.
Now there are 7 item(s) in set1.
Now there are 8 item(s) in set1.
Now there are 9 item(s) in set1.
Now there are 10 item(s) in set1.
Now there are 11 item(s) in set1.
Now there are 12 item(s) in set1.
Now there are 13 item(s) in set1.
Now there are 14 item(s) in set1.
Now there are 15 item(s) in set1.
Now there are 16 item(s) in set1.
Now there are 17 item(s) in set1.
Now there are 18 item(s) in set1.
Now there are 19 item(s) in set1.
Now there are 20 item(s) in set1.
Now there are 21 item(s) in set1.
Now there are 22 item(s) in set1.
Now there are 23 item(s) in set1.
Now there are 24 item(s) in set1.
Now there are 25 item(s) in set1.
Now there are 26 item(s) in set1.
Now there are 27 item(s) in set1.
Now there are 28 item(s) in set1.
Now there are 29 item(s) in set1.
Now there are 30 item(s) in set1.
Erase one item from set1.
Succeed to erase 28 from set1
no 28 in set1.
Now there are 29 item(s) in set1.
Declare set2
Insert 2 into set2
set2 = set1 + set2
How many 2s in set2?
Here are 1 2(s)
Try to erase 2 from set2.
Erase 1 2(s) from set2
How many 2s in set2 now?
Here are 0 2(s)
How many item(s) in set2 now?
Here are 28 item(s) in set2 now.
set3 = set1 - set2
The size of set3: 1
Data Structures and Other Objects Using C++ ( Fourth Edition ) Michael Main, Walter Savitch. p179 ↩︎