2

以下を実装する最良の方法は何ですか?2セットの結合を見つけようとしています。2 つのオブジェクトを作成しています (1 つは set1 と呼ばれ、もう 1 つは set2 と呼ばれます)。コピー コンストラクターを使用せずに、2 つの UNION である 3 番目のオブジェクトを作成することを目指しています。動的メモリ割り当てとポインターおよび/または参照の使用は必須です。このジレンマを解決してくれた人に感謝します.

コーダーに感謝します。

ヘッダファイル

                #ifndef INTEGERSET_H_
                #define INTEGERSET_H_

                class IntegerSet
                {
                private:
                    int * set;
                    int set_size;
                public:
                    IntegerSet(int size);    //default constructor
                    ~IntegerSet();           //destructor
                    IntegerSet * unionOfSets(const IntegerSet & set2);      
                    void insertElement(int k) const;
                    void printSet(int size) const;
                };
                #endif

メインファイル

            #include <iostream>
            #include "integerset.h"

            using std::cout;
            using std::endl;

            int main()
            {
                IntegerSet set1(11);

                //testing below
                set1.insertElement(3);
                set1.insertElement(4);
                set1.insertElement(6);
                set1.insertElement(10);

                set1.printSet(11);
                cout << endl;

                IntegerSet set2(8);
                set2.insertElement(3);
                set2.insertElement(6);
                set2.insertElement(7);

                set2.printSet(11);
                cout << endl;



                IntegerSet * obj3 = new IntegerSet(11);
                obj3 =  set1.unionOfSets(set2);                    
                obj3->printSet(11);

            //  system("pause");
                return 0;
            }

実装ファイル

            #include "integerset.h"
            #include <iostream>

            IntegerSet::IntegerSet(int size)
            {
                set = new int[size];
                set_size = size;                    
                for (int i = 0; i < size; i++)
                    set[i] = 0;
            }

            IntegerSet::~IntegerSet()
            {
                delete [] set;
            }

            void IntegerSet::insertElement(int k) const
            {
                (*this).set[k] = 1;
            }

            void IntegerSet::printSet(int size) const
            {
                int temp = 0;
                for (int i = 0; i < size; i++)
                {
                    if (set[i] == 1)
                    {
                        std::cout << i << " ";
                        temp++;
                    }
                }
                if (temp == 0)
                    std::cout << "----";
             }


            IntegerSet * IntegerSet::unionOfSets(const IntegerSet & set2) //make this return the union of 2 sets; THIS and the passed ARG reference; return address
            {


                   return this;
            }
4

2 に答える 2

4

ランダムな朝の暴言

あなたが作ろうとしているのは、以上のstd::bitsetものstd::setです。セットは通常、「明確に定義された個別のオブジェクトのコレクション」です(カントールの定義はもう少し複雑ですが、これに固執しましょう)。そのため、セットには、ペアごとに無関係なオブジェクトがいくつか含まれる場合があります。

さて、これが言われた後、見てくださいstd::bitset。そのサイズはテンプレート パラメータによって固定されていることに注意してくださいN。をスローすることを除いて、std::bitset::setyour とほぼ同等です。これにより、有効な位置についてインデックスを確認することをお勧めします。IntegerSet::insertElementstd::out_of_range

void IntegerSet::insertElement(int k) const
{
    if( k < 0 || k >= set_size)
        throw std::out_of_range; 
    else
        this->set[k] = 1;
}

ただし、std::bitsetユニオンはサポートしていません。

IntegerSet::unionofSets

それらの行を見てください。

IntegerSet * obj3 = new IntegerSet(11);
obj3 =  set1.unionOfSets(set2);

最初の行obj3は、サイズ 11 の内部セットを持つ新しく作成された IntegerSet のメモリを含むポインターで初期化します。次の行で、そのポインターを捨てます。したがって、リソースを捨てて、メモリ リークを作成しています。

新しいIntegerSetを作成する場合、ソリューションは非常に単純になります。

IntegerSet IntegerSet::unionOfSets(const IntegerSet & set2) const
{
    IntegerSet tmp (std::max(set2.set_size, this->set_size));

    for(int i = 0; i < set_size; ++i)
        tmp.set[i] = this->set[i];

    for(int i = 0; i < set2.set_size; ++i)
        tmp.set[i] |= set2.set[i];

    return tmp;
}

しかし、あなたの実装はそれが呼び出されたオブジェクトを変更するので、そうではなくconst、少し異なります:

IntegerSet * IntegerSet::unionOfSets(const IntegerSet & set2) // not const!
{
    if(set2.set_size > set_size){
        // the resulting set is bigger, we need new memory
        int * newset = new int[set2.set_size];

        // copy old values
        for(int i = 0; i < this->set_size; ++i)
            newset[i] = this->set[i];

        // replace old size
        this->set_size = set2.set_size;
        delete[] this->set; // remove old data
        this->set = newset; // replace pointer
    }

    for(int i = 0; i < set2.set_size; ++i)
        this->set[i] |= set2.set[i];

    return this;
}

これで十分です。new IntegerSetユニオンを作成するために使用してはならないことに注意してください。

IntegerSet * obj3 = new IntegerSet(11); // new memory, lets say obj3 = 0x500a
obj3 = set1.unionOfSets(set2); // new memory gone forever

if(obj3 == &set1)
    std::cout << "obj3 is a pointer to set1, changes to obj3 will affect set1" << std::endl;

この動作を作成したくない場合は、最初のバージョンを一時的に使用してください。

また、 からもご利用いただけますので、十分かご確認std::set<int>ください。std::set_union<algorithm>

編集

  1. 2 つの既存の IntegerSet インスタンスの和集合である 3 番目の IntegerSet を作成する unionOfSets メンバー関数を提供します (したがって、この関数によって作成される 3 番目のセットには、作成に使用された 2 つのセットのすべてのメンバーが含まれます。したがって、セットの一方または両方が結合が実行され、要素が含まれている場合、3 番目のセットにはその要素が含まれます)

この場合、忘れてIntegerSet * IntegerSet::unionOfSets(const IntegerSet&)使用しますIntegerSet IntegerSet::unionOfSets(const IntegerSet&) const(返されたポインターの代わりに返されたオブジェクトを持つ最初のバリアント)。

EDIT2

3 のルールに従わなかったので、返されたメモリはIntegerSet無効になります。これを修正するには、コピー コンストラクター/代入演算子を実装するか、動的ストレージ期間 ( new) を持つ新しいオブジェクトを提供する必要があります。このためには、メソッドを少し調整する必要があります。

IntegerSet * IntegerSet::unionOfSets(const IntegerSet & set2) const
{
    IntegerSet * tmp  = new IntegerSet( set2.set_size > this->set_size ? set2.set_size : this->set_size);

    for(int i = 0; i < set_size; ++i)
        tmp->set[i] = this->set[i];

    for(int i = 0; i < set2.set_size; ++i)
        tmp->set[i] |= set2.set[i];

    return tmp;
}
于 2012-10-05T05:25:33.113 に答える
1

標準設備を利用して...

  • std::vector手巻きの配列よりも優れています
  • std::sortそしてstd::unique良さです

したがって:

std::vector<int> set1;
set1.push_back(1); // ... and others

std::sort(set1.begin(), set1.end());   // sorts
std::unique(set1.begin(), set1.end()); // removes duplicates


// same with set2


std::vector<int> set3(set1);
set3.insert(set3.end(), set2.begin(), set2.end());

std::sort(set1.begin(), set1.end());   // sorts
std::unique(set1.begin(), set1.end()); // removes duplicates
于 2012-10-05T07:44:26.877 に答える