简体   繁体   中英

How to Find The Intersection of two Bags

Ok so I have this code down.

Bag interface

#ifndef BAGINTERFACE_H
#define    BAGINTERFACE_H

#include <vector>
#include <algorithm>

template<class ItemType>
class BagInterface
{
    public:

    virtual int getCurrentSize() const = 0;
    virtual bool isEmpty() const = 0;
    virtual bool add(const ItemType& newEntry) = 0;
    virtual bool remove(const ItemType& anEntry) = 0;
    virtual void clear() = 0;
    virtual int getFrequencyOf(const ItemType& anEntry) const = 0;
    virtual bool contains(const ItemType& anEntry) const = 0;
    virtual std::vector<ItemType> toVector() const = 0;
}; 

#endif    /* BAGINTERFACE_H */

Bag #ifndef BAG_H #define BAG_H

#include "BagInterface.h"

template <class ItemType>
class Bag: public BagInterface<ItemType>
{

public:

    int getCurrentSize() const { return v.size(); }
    bool isEmpty() const { return v.empty(); }
    bool add(const ItemType& newEntry) { v.push_back(newEntry); return true; }
    bool remove(const ItemType& anEntry) { std::remove(v.begin(), v.end(), anEntry); return true; }
    void clear() { v.clear(); }
    int getFrequencyOf(const ItemType& anEntry) const { return std::count(v.begin(), v.end(), anEntry); }
    bool contains(const ItemType& anEntry) const { return true; }
    std::vector<ItemType> toVector() const { return v; }

private:

  std::vector<ItemType> v;

};

#endif    /* BAG_H */

and my actual program main.cpp

#include <iostream> // For cout and cin
#include <string> // For string objects
#include "Bag.h" // For ADT bag
using namespace std;
int main()
{
string clubs[] = { "Joker", "Ace", "Two", "Three",
"Four", "Five", "Six", "Seven",
"Eight", "Nine", "Ten", "Jack",
"Queen", "King" };
// Create our bag to hold cards
Bag<string> grabBag;
Bag<string> dumpBag;

grabBag.add(clubs[1]);
grabBag.add(clubs[2]);
grabBag.add(clubs[4]);
grabBag.add(clubs[8]);
grabBag.add(clubs[10]);
grabBag.add(clubs[12]);

dumpBag.add(clubs[3]);
dumpBag.add(clubs[5]);
dumpBag.add(clubs[7]);
dumpBag.add(clubs[9]);
dumpBag.add(clubs[10]);
dumpBag.add(clubs[12]);

Bag<string> Itersection(Bag<string> bagToCompare){


    return grabBag;
}


return 0;
}; // end main

I am trying to find the intersection of two bags which will be a new bag containing the entries that occur in both of the original two bags. So basically I need to design and specify a method intersection that returns as a new bag the intersection of the bag receiving the call to the method and the bag that is the method's one argument. Suppose that bag1 and bag2 are bags; bag1 contains the strings a , b , and c ; and bag2 contains the strings b , b , d , and e . The expression bag1.intersection(bag2) returns a bag containing only the string b.

I already made the two bags to compare to each other but I'm not too sure how to design the intersection method.

Any help would be great. Thank you.

Since the only way to enumerate the items in a bag is by using toVector , you need to iterate over the toVector of one of your input bags. For each item, take the minimum frequency of that item in either of the input bags, and make sure the output bag contains the item with that frequency. Since the toVector might contain the same item repeatedly, you have to check the output bag to see if it already contains the item you're considering.

I'm not up to speed on C++11, so I'll just do this an old-fashioned way:

template<class T>
Bag<T> intersection(BagInterface<T> const &a, BagInterface<T> const &b) {
    Bag<T> c;
    std::vector<T> aItems = a.toVector();
    for (int i = 0; i < aItems.size(); ++i) {
        T const &item = aItems[i];
        int needed = std::min(a.getFrequencyOf(item), b.getFrequencyOf(item));
        int lacking = needed - c.getFrequencyOf(item);
        for ( ; lacking > 0; --lacking) {
            c.add(item);
        }
    }
    return c;
}

Try using enum for clubs. You can use strings, but string comparsion is tricky.

enum ClubsType { 
    Joker, 
    Ace, 
    Two, 
    Three, 
    Four, 
    Five, 
    Six, 
    Seven, 
    Eight, 
    Nine, 
    Ten, 
    Jack, 
    Queen, 
    King,
    ClubsTypeSize
}

Bag<ClubsType> Intersection(const Bag<ClubsType>& other) {
    set<ClubsType> common;
    int n = v.size();
    for (int i=0;i<n;i++) {
        common.insert(v[i]);
    }
    otherAsVector = other.toVector();
    n = otherAsVector.size();
    for (int i=0;i<n;i++) {
        common.insert(otherAsVector[i]);
    }
    Bag<ClubsType> result;
    for (set<ClubsType>::iterator it = common.begin(); it!=common.end();++it) {
        result.add(*it);
    }
    return result;
}

std::set_intersection from <algorithm> does this for sorted input ranges:

vector<int> as { 1, 2, 3 };
vector<int> bs { 2, 3, 4 };
vector<int> cs;

set_intersection(
    begin(as), end(as),
    begin(bs), end(bs),
    back_inserter(cs)
);

// 2 3
for (const auto c : cs)
    cout << c << ' ';

It works by looping over the input ranges until at least one is exhausted, copying those elements from one range that appear in the other, according to the strict weak ordering imposed by operator< :

while (first1 != last1 && first2 != last2) {
    if (*first1 < *first2) {
        ++first1;
    } else {
        if (!(*first2 < *first1)) {
            *output++ = *first1++;
        }
        ++first2;
    }
}
return output;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM