2

ベクトル内の同じ整数を削除しようとしています。私の目標は、それらを 1 つだけコピーすることです。さて、簡単なコードを書きましたが、正しく動作しません。誰でも助けることができますか?前もって感謝します。

#include <iostream>
#include <vector>
using namespace std;

int main()

{   

int a = 10, b = 10 , c = 8, d = 8, e = 10 , f = 6;
vector<int> vec;

vec.push_back(a);
vec.push_back(b);
vec.push_back(c);
vec.push_back(d);
vec.push_back(e);
vec.push_back(f);


for (int i=vec.size()-1; i>=0; i--)
{
    for(int j=vec.size()-1; j>=0; j--)
    {
        if(vec[j] == vec[i-1])
            vec.erase(vec.begin() + j);
    }
}   

for(int i=0; i<vec.size(); i++)
{
    cout<< "vec: "<< vec[i]<<endl;
}

return 0;
}
4

6 に答える 6

3

これにはリストを使用しないでください。セットを使用します。

 #include <set>
 ...
 set<int> vec;

これにより、要素が既に存在する場合は要素を追加しないことで、重複がなくなります。

于 2013-10-18T17:08:56.193 に答える
2

範囲の本体は、反復するシーケンスのサイズを変更してはなりません..

push_back の前に重複を削除できます

void push(std::vector<int> & arr, int n)
{

    for(int i = 0; i != arr.size(); ++i)
    {
        if(arr[i] == n) 
        {
            return;
        }
    }
    arr.push_back(n);
}

... ... 

push(vec, a);

push(vec, b);

push(vec, c);
... 
于 2013-10-18T17:50:09.223 に答える
2

重複を削除するには、最初に配列をソートすると簡単です。以下のコードでは、重複を削除するために 2 つの異なる方法を使用しています。1 つは組み込みの C++ アルゴリズムを使用し、もう 1 つはループを使用しています。

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

using namespace std;

int main() {
    int a = 10, b = 10 , c = 8, d = 8, e = 10 , f = 6;
    vector<int> vec;
    vec.push_back(a);
    vec.push_back(b);
    vec.push_back(c);
    vec.push_back(d);
    vec.push_back(e);
    vec.push_back(f);

    // Sort the vector
    std::sort(vec.begin(), vec.end());

    // Remove duplicates (v1)
    std::vector<int> result;
    std::unique_copy(vec.begin(), vec.end(), std::back_inserter(result));

    // Print results
    std::cout << "Result v1: ";
    std::copy(result.begin(), result.end(), std::ostream_iterator<int>(cout, " "));
    std::cout << std::endl;

    // Remove duplicates (v2)
    std::vector<int> result2;
    for (int i = 0; i < vec.size(); i++) {
        if (i > 0 && vec[i] == vec[i - 1])
            continue;
        result2.push_back(vec[i]);
    }

    // Print results (v2)
    std::cout << "Result v2: ";
    std::copy(result2.begin(), result2.end(), std::ostream_iterator<int>(cout, " "));
    std::cout << std::endl;

    return 0;
}
于 2013-10-18T17:30:12.447 に答える
2

他の人はすでに指摘していstd::setます。これは確かにシンプルで簡単ですが、かなり遅くなる可能性があります (std::vectorリンク リストのように) 個別に割り当てられたノードで構成され、ポインターを介してリンクされてバランスの取れたツリーを形成するためです1

std::unordered_setの代わりに を使用することで、(多くの場合)改善できますstd::set。これは、データを格納するためにツリーの代わりにハッシュ テーブル2を使用するため、通常は連続したストレージを使用し、ツリーに予想される O(log N) ではなく O(1) の予想アクセス時間を与えます。

多くの場合、より高速な代替手段は、ベクターでデータを収集し、データを並べ替えて、std::unique重複を排除するために使用することです。これは、操作の 2 つの異なるフェーズがある場合に最適な傾向があります。最初にすべてのデータを収集し、次に重複を削除する必要があります。データの追加/削除を頻繁に繰り返し、フリー セットの複製が必要な場合は、std::setまたはstd::unordered_setセットを常に複製せずに維持するようなものがより役立つ場合があります。

これらはすべて、アイテムの順序にも影響します。は、定義された順序で並べ替えられたstd::setアイテムを常に維持します。データを明示的にstd::uniqueソートする必要があります。std::unordered_set元の順序でもソートされていない任意の順序でソートされたアイテムを取得します。

元の順序を維持する必要があるが、重複がない場合は、通常、データを 2 回保存する必要があります。たとえば、新しいアイテムを追加する必要がある場合は、それを に挿入しようとしstd::unordered_set、それが成功した場合にのみ、それをベクターにも追加します。


  1. 技術的には、ツリーとしての実装は厳密には必要ありませんが、要件を満たすことができると私が認識している唯一の可能性についてであり、私が認識しているすべての実装はツリーに基づいています。

  2. 繰り返しになりますが、他の実装も理論的には可能かもしれませんが、私が知っているすべてでハッシュを使用していますが、この場合、ハッシュテーブルを回避することはおそらくさらに困難になるほどの実装が公開されています.

于 2013-10-18T17:28:57.097 に答える
2

コードの問題は次のとおりです。

for(int j=vec.size()-1; j>=0; j--)
{
    if(vec[j] == vec[i-1])
        vec.erase(vec.begin() + j);
}

j==i-1アルゴリズムがi-1 < 0停止し、境界外の例外が発生する場合があります。

できることは、for ループの条件を変更することです。

for (int i = vec.size() - 1; i>0; i--){
    for(int j = i - 1; j >= 0; j--){
        //do stuff
    }
}

このように、比較する 2 つの変数が同じになることはなく、インデックスは常に少なくとも 0 になります。

于 2013-10-18T17:12:40.047 に答える