简体   繁体   English

如何找到两个袋子的交点

[英]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 手提袋#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 和我的实际程序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和bag2是bag; bag1 contains the strings a , b , and c ; bag1包含字符串a,b和c; and bag2 contains the strings b , b , d , and e . bag2包含字符串b,b,d和e。 The expression bag1.intersection(bag2) returns a bag containing only the string b. 表达式bag1.intersection(bag2)返回仅包含字符串b的bag。

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. 由于枚举袋中物品的唯一方法是使用toVector ,因此您需要遍历一个输入袋的toVector 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. 由于toVector可能重复包含相同的项目,因此您必须检查输出包以查看它是否已包含您要考虑的项目。

I'm not up to speed on C++11, so I'll just do this an old-fashioned way: 我没有赶上C ++ 11的步伐,所以我只是用一种老式的方式来做:

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: <algorithm> std::set_intersection对已排序的输入范围执行此操作:

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< : 它根据输入范围的循环进行操作,直到至少一个耗尽为止,然后根据operator<施加的严格弱排序从一个范围复制出现在另一个范围内的那些元素。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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