あなたの質問で示唆している解決策は、細部を除いて、実際に必要なものだと思います。
あなたは提案しました:
格納する必要がある要素の最大数にメモリを事前に割り当ててから、常に新しい要素を最後に配置して、他の要素の再割り当てや移動が不要になるようにすることができると思いました。
実際にエントリの妥当な最大数を確立できる場合は、そのエントリ数で配列を事前に割り当て (たとえばstd::array
、コンパイル時に最大値がわかっている場合などに使用std::vector
)、要素数を確立することをお勧めします (現在保存されている要素の数を数えます)、次のように進みます。
- 最初にカウントを0に設定します
- 要素を挿入するときは、最後に追加してカウントを増やします
- 要素を削除すると、それを最後の要素と交換し、カウントを減らします
- ランダムアクセス(説明した意味で、つまり文字通り要素をランダムに選択する)の場合、0とカウントの間の乱数を決定し、その要素を選択します
私が変更した唯一の詳細は要素の削除です。これは、最後の要素でスイッチ位置として実装することをお勧めします。
可能な実装:
#include <vector>
#include <utility>
#include <iostream>
template <typename Elem>
class randomaccesstable
{
public:
randomaccesstable(std::size_t initial_size)
: data_(initial_size) , count_(0)
{ }
randomaccesstable &push_back(const Elem &elem)
{
if (count_ < data_.size())
data_[count_++] = elem;
else {
data_.push_back(elem);
++count_;
}
return *this;
}
randomaccesstable &remove(const std::size_t index)
{
if (index < count_)
{
std::swap(data_[index],data_[count_-1]);
--count_;
}
return *this;
}
const Elem &operator[](const std::size_t index) const
{ return data_[index]; }
Elem &operator[](const std::size_t index)
{ return data_[index]; }
std::size_t size() const
{ return count_; }
private:
std::vector<Elem> data_;
std::size_t count_;
};
int main()
{
randomaccesstable<int> table(10);
table.push_back(3);
table.push_back(12);
table.push_back(2);
for (std::size_t i = 0 ; i < table.size() ; ++i)
std::cout << table[i] << ' ';
std::cout << '\n';
table.remove(1); // this removes the entry for 12, swapping it for 2
for (std::size_t i = 0 ; i < table.size() ; ++i)
std::cout << table[i] << ' ';
std::cout << '\n';
return 0;
}