=====コンテナクラス=====
STL のコンテナクラスを使いこなせれば処理が楽になることは往々にしてある.\\
時間があれば適切なコンテナクラスを使うことに挑戦してみるのがよい
以下は自分が使ったもの
===vector===
C++ の reference は[[https://cpprefjp.github.io/reference/vector/vector.html|ここ]]にある.\\
要素の順序を保存するクラスであり,要素数が自動的に拡張される一次元配列のイメージ.\\
添字によるランダムアクセスが高速で行なえ,配列の最後尾に要素を追加していくイメージで使用することが多い.\\
末尾以外への挿入がメインの操作であったり,シーケンシャルアクセスの速さが必要な場合は list や deque を使うらしい.
for loop の回し方を以下に示しておく.
#include
#include
int main(){
std::vector v = {1, 3, 4};
for ( auto iv : v ) {
std::cout << iv << std::endl;
}
// 1
// 3
// 4
v.push_back(5);
for ( auto itr = v.begin(); itr != v.end(); itr++ ) {
std::cout << *itr << std::endl;
}
// 1
// 3
// 4
// 5
v.at(0) = 0;
for ( int i = 0; i < v.size(); i++ ) {
std::cout << v.at(i) << std::endl;
}
// 0
// 3
// 4
// 5
std::cout << v.front << ", " << v.back << std::endl;
// 0, 5
}
その他''resize'', ''empty'', ''reserve'', ''clear'', ''shrink_to_fit'' などの使い方を調べてみるとよい.
===array===
C++ の reference は[[https://cpprefjp.github.io/reference/array/array.html|ここ]]にある.\\
要素の順序を保存するクラスであり,vector と違って要素数が決まっている.\\
個人的には vector を使っていればよいと思うので,あまり使っていない.\\
ROOT では array はバグの温床なので使わないほうがよい.
===set===
C++ の reference は[[https://cpprefjp.github.io/reference/set/set.html|ここ]]にある.\\
数学における集合に相当し,ユニークな要素を収納するクラス.\\
「**ある要素があるかないか**」という特徴から探索をすることに特化しており,次の map において要素自身がキーとなっていることに相当する.\\
「コンテナの何番目」という特徴から探すのであれば vector や array がよい.\\
要素はユニークでなければならず,複数の要素を許すには multiset を用いる.
たとえば ''std::set > linklets'' としてあるグループに含まれる linklet の set を使った.\\
linklet は重複が考えられるが,重複する linklet を考える意味はなく,また順番よりもある linklet の有無が気になることがあるため. (もちろんアルゴリズムによる)\\
なお,こんな長い型は本来は適当に以下のように typedef するべきである.
typedef std::set > B2PairSet;
set は二分木で探索する際に要素の順序を用いるため,少なくとも**不等号**が必要. (default は ''less'')\\
自作クラスについては''operator<'' を定義する必要がある.\\
operator のオーバーロードの仕方は[[programming:cpp:class|ここ]]を参照.
#include
#include
int main (int argc, char *argv[]) {
std::set test_set;
// 要素の追加
test_set.insert(1);
test_set.insert(2);
// 同じ要素は追加されない
test_set.insert(2);
// insert の戻り値は std::pair になっている.
// first は追加された場合はその iterator を,そうでない場合はすでにその要素が存在する iterator を指す
// second は追加された場合は true を,そうでない場合は false を出力する
// 順番にソートされている
// ただし順番にしたいだけなら vector を sort したほうがよい
for ( auto itr = test_set.begin(); itr != test_set.end(); itr++ ) {
std::cout << *itr << std::endl;
}
// 1
// 2
// 値が set に存在するかを確認
if ( test_set.find(1) != test_set.end() )
std::cout << "Found" << std::endl;
else
std::cout << "Not found" << std::endl;
// Found
std::exit(0);
}
===map===
C++ の reference は[[https://cpprefjp.github.io/reference/map/map.html|ここ]]にある.\\
ユニークな要素をキーと関連付けて収納するクラス.\\
要素に対して「**あるキーを持っている**」という特徴から探索をすることに特化したコンテナクラス.\\
「コンテナの何番目」という特徴から探すのであれば vector や array がよい.\\
キーと要素は 1:1 対応でなければならず,あるキーに対して複数の要素を許すには multimap を用いる.
たとえば ''std::map track_id_map'' として track id と B2 class の map を使った.\\
これは ''track->GetTrackId()'' とは別の id が emulsion 側とのインターフェースのために振られているためで,解析のフローを改良するべきだという意見は大いにある.
map は二分木で探索する際にキーの順序を用いるため,少なくとも**不等号**が必要. (default は ''less'')\\
自作クラスについては''operator<'' を定義する必要がある.\\
operator のオーバーロードの仕方は[[programming:cpp:class|ここ]]を参照.
#include
#include
===multimap===
C++ の reference は[[https://cpprefjp.github.io/reference/map/multimap.html|ここ]]にある.\\
map において一つのキーに対して複数の要素を許すようにしたもの.
#include
#include
===unordered_multimap===
一般的には hash multimap と呼ばれる.\\
キーの順番に従って並べられるわけではなく,キーから要素を取り出すことに特化したコンテナクラスとなっている(らしい).
std にも導入されているが,自分は boost のものを使用した.
unordered なコンテナを使う際には等号とハッシュ関数が必要.\\
自作クラスについてはこれらを定義する必要がある.\\
それぞれの関数のオーバーロードの仕方は[[programming:cpp:class|ここ]]を参照.
#include
#include
#include
#include
int main (int argc, char *argv[]) {
// linklet の実装.
// ただし実は MC の解析であれば unordered である必要はなかった.
boost::unordered_multimap linklet;
std::vector > linklets;
for ( auto ilinklet : linklets ) {
if ( ilinklet.first > ilinklet.second )
std::swap(ilinklet.first, ilinklet.second);
linklet.insert(std::make_pair(linilet.first, linklet.second));
}
// これで上流の basetrack を基準につながる下流の basetrack を高速で探索することが可能となった.
// ただし,実際には int ではなく,plate などで大小関係が決まった構造体を詰めている
// ある basetrack からつながるすべての basetrack を列挙する.
int target = 100;
if ( linklet.find(target) != linklet.end() ) {
auto range = linklet.equal_range(target);
for ( auto itr = range.first; itr != range.second; itr++ ) {
std::cout << (*itr).second << std::endl;
}
}
std::exit(0);
}