この問題に出くわしました。通常のstd::set
のインデックスの位置にあるアイテムを選択できないようです。これはSTDのバグですか?
以下に簡単な例を示します。
#include <iostream>
#include <set>
int main()
{
std::set<int> my_set;
my_set.insert(0x4A);
my_set.insert(0x4F);
my_set.insert(0x4B);
my_set.insert(0x45);
for (std::set<int>::iterator it=my_set.begin(); it!=my_set.end(); ++it)
std::cout << ' ' << char(*it); // ups the ordering
//int x = my_set[0]; // this causes a crash!
}
問題を解決するためにできることはありますか?
それはクラッシュを引き起こさず、単にコンパイルしません。 set
にはインデックスによるアクセスがありません。
次のようにn番目の要素を取得できます。
_std::set<int>::iterator it = my_set.begin();
std::advance(it, n);
int x = *it;
_
もちろん、my_set.size() > n
と仮定します。この操作には、n
にほぼ比例して時間がかかることに注意してください。 C++ 11には、これをより適切に記述する方法があります。
_int x = *std::next(my_set.begin(), n);
_
繰り返しますが、n
が最初に境界内にあることを知っておく必要があります。
std :: set の通常の実装は、 binary search trees を使用することです。特に red-balancing binary search trees など red -黒い木
これらは、n番目の要素への一定時間のアクセスを提供しません。しかし、あなたは最初のものが欲しいようです。 C++ 11 で試してください:
auto it = my_set.begin();
int first=0;
if (it != my_set.end()) first = *it;
インデックスを作成できるセットが必要な理由がある場合があります。呼び出し元がアイテムを列挙できるように、アイテムの数とインデックスのアイテムを返す機能を備えたレガシーAPIをサポートするために、最近この機能を実装する必要がありました。
問題を解決する私の方法は、std :: vectorを使用し、std :: equal_rangeを使用して、セット内のアイテムを検索および挿入または削除することです。たとえば、新しいアイテムをセットに挿入すると次のようになります。
std:vector<std::string> my_set;
...
std::string new_item("test");
auto range = std::equal_range(my_set.begin(),my_set.end(),new_item);
if (range.first == range.second)
my_set.insert(range.first,new_item);
削除は非常に似ています。equal_rangeを使用してアイテムを見つけ、range.firstがnot range.secondと等しい場合、その範囲を削除します。
一定の時間でアクセスできる方法はありません。
ただし、O(n)時間で任意の要素に到達できます。
std::set<int>::iterator it;
it=my_set.begin();
advance(it,n);
cout<<*it;
これはSTDのバグではありません。 std::set
にはランダムアクセスはありません。インデックスによるランダムアクセスが必要な場合は、std::vector
を使用できます