User Tools

Site Tools


programming:cpp:container

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
programming:cpp:container [2022/04/13 10:40]
odagawa
programming:cpp:container [2022/05/06 17:25] (current)
odagawa
Line 14: Line 14:
  
 for loop の回し方を以下に示しておく. for loop の回し方を以下に示しておく.
- 
  
 <code cpp> <code cpp>
 +#include <iostream>
 #include <vector> #include <vector>
  
Line 62: Line 62:
 要素の順序を保存するクラスであり,vector と違って要素数が決まっている.\\ 要素の順序を保存するクラスであり,vector と違って要素数が決まっている.\\
 個人的には vector を使っていればよいと思うので,あまり使っていない.\\ 個人的には vector を使っていればよいと思うので,あまり使っていない.\\
-ROOT では std::array はバグの温床なので使わないほうがよい.+ROOT では array はバグの温床なので使わないほうがよい.
  
 ===set=== ===set===
Line 73: Line 73:
  
 たとえば ''std::set<std::pair<B2EmulsionSummary*, B2EmulsionSummary* > > linklets'' としてあるグループに含まれる linklet の set を使った.\\ たとえば ''std::set<std::pair<B2EmulsionSummary*, B2EmulsionSummary* > > linklets'' としてあるグループに含まれる linklet の set を使った.\\
-linklet は重複が考えられるが,重複する linklet を考える意味はなく,また順番よりもある linklet の有無が気になることがあるため. (もちろんアルゴリズムによる)+linklet は重複が考えられるが,重複する linklet を考える意味はなく,また順番よりもある linklet の有無が気になることがあるため. (もちろんアルゴリズムによる)\\ 
 +なお,こんな長い型は本来は適当に以下のように typedef するべきである. 
 +<code cpp> 
 +typedef std::set<std::pair<B2EmulsionSummary*, B2EmulsionSummary* > > B2PairSet; 
 +</code>
  
 set は二分木で探索する際に要素の順序を用いるため,少なくとも**不等号**が必要. (default は ''less<Key>'')\\ set は二分木で探索する際に要素の順序を用いるため,少なくとも**不等号**が必要. (default は ''less<Key>'')\\
-自作クラスについては''operator<'' を定義する必要がある.+自作クラスについては''operator<'' を定義する必要がある.\\ 
 +operator のオーバーロードの仕方は[[programming:cpp:class|ここ]]を参照. 
 + 
 +<code cpp> 
 +#include <iostream> 
 +#include <set> 
 + 
 +int main (int argc, char *argv[]) { 
 + 
 +  std::set<int> test_set; 
 +   
 +  // 要素の追加 
 +  test_set.insert(1); 
 +  test_set.insert(2); 
 +  // 同じ要素は追加されない 
 +  test_set.insert(2); 
 +  // insert の戻り値は std::pair<iterator, bool> になっている. 
 +  // 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); 
 +   
 +
 +</code>
  
 ===map=== ===map===
Line 90: Line 132:
  
 map は二分木で探索する際にキーの順序を用いるため,少なくとも**不等号**が必要. (default は ''less<Key>'')\\ map は二分木で探索する際にキーの順序を用いるため,少なくとも**不等号**が必要. (default は ''less<Key>'')\\
-自作クラスについては''operator<'' を定義する必要がある.+自作クラスについては''operator<'' を定義する必要がある.\\ 
 +operator のオーバーロードの仕方は[[programming:cpp:class|ここ]]を参照
  
-例えば int と double をもつクラスをキーとして使う場合は, +<code cpp> 
-<code cpp MyClass.hpp+#include <iostream> 
-#ifndef MYCLASS_HPP +#include <map>
-#define MYCLASS_HPP+
  
-class MyClass { +int main (int argc, char *argv[]{
-public :  +
-  int var1; +
-  double var2; +
-   +
-  bool operator<(const MyClass &rhsconst; +
-};+
  
-#endif+  std::map<int, std::string> month_map; 
 +   
 +  // 要素の追加は make_pair を用いて行う 
 +  month_map.insert(std::make_pair(1, "January")); 
 +  month_map.insert(std::make_pair(2, "February")); 
 +  month_map.insert(std::make_pair(3, "March")); 
 +  // 同じキーに対応する要素は追加されない 
 +  month_map.insert(std::make_pair(3, "San-gatsu")); 
 +   
 +  // キーの順番にソートされている 
 +  for ( auto itr = month_map.begin(); itr != month_map.end(); itr++ ) { 
 +    std::cout << (*itr).first << "月 : " << (*itr).second << std::endl; 
 +  } 
 +  // 1月 : January 
 +  // 2月 : February 
 +  // 3月 : March 
 +   
 +  // キーの値で月を探索 
 +  std::string second_month = month_map.at(2); 
 +  std::cout << second_month << std::endl; 
 +  // February 
 +   
 +  std::exit(0); 
 +   
 +}
 </code> </code>
  
-<code cpp MyClass.cpp> +===multimap=== 
-#include "MyClass.hpp"+ 
 +C++ の reference は[[https://cpprefjp.github.io/reference/map/multimap.html|ここ]]にある.\\ 
 +map において一つのキーに対して複数の要素を許すようにしたもの. 
 + 
 +<code cpp> 
 +#include <iostream> 
 +#include <map> 
 + 
 +int main (int argv, char *argv[]) { 
 + 
 +  std::multimap<int, std::string> month_map; 
 + 
 +  // 要素の追加は make_pair を用いて行う 
 +  month_map.insert(std::make_pair(1, "January")); 
 +  month_map.insert(std::make_pair(2, "February")); 
 +  month_map.insert(std::make_pair(3, "March")); 
 +  // 同じキーに対応する要素は追加される 
 +  month_map.insert(std::make_pair(3, "San-gatsu")); 
 +   
 +  // あるキーに対応する値をすべて探索 
 +  auto range = month_map.equal_range(3); 
 +  // equal_range の戻り値はキーが対応する最初と最後+1のイテレータの pair 
 +  // std::pair<iterator, iterator> である 
 +  for ( auto itr = range.first; itr != range.second; itr++ ) { 
 +    std::cout << (*itr).second << std::endl; 
 +  } 
 +  // March 
 +  // San-gatsu 
 +   
 +  std::exit(0);
  
-bool MyClass::operator<(const MyClass &rhs) const { 
-  if ( var1 != rhs.var1 ) 
-    return var1 < rhs.var1; 
-  return var2 < rhs.var2 
 } }
 +
 </code> </code>
  
 ===unordered_multimap=== ===unordered_multimap===
  
-std でも boost よい+一般的には hash multimap と呼ばれる.\\ 
 +キーの順番に従って並べられるわけはなく,キーから要素を取り出すことに特化したコンテナクラスとなっている(らしい). 
 +std に導入されているが,自分は boost のを使用した.
  
 unordered なコンテナを使う際には等号とハッシュ関数が必要.\\ unordered なコンテナを使う際には等号とハッシュ関数が必要.\\
 自作クラスについてはこれらを定義する必要がある.\\ 自作クラスについてはこれらを定義する必要がある.\\
-boost の unordered_multimap 例を以下に示す. +それぞれ関数オーバーロードは[[programming:cpp:class|ここ]]を参照.
-hash 作り+
  
 +<code cpp>
 +#include <iostream>
 +#include <vector>
 +#include <utility>
 +
 +#include <boost/unordered_map.hpp>
 +
 +int main (int argc, char *argv[]) {
 +
 +  // linklet の実装.
 +  // ただし実は MC の解析であれば unordered である必要はなかった.
 +  boost::unordered_multimap<int, int > linklet;
 +  
 +  std::vector<std::pair<int, int > > 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);
 +
 +}
 +
 +</code>
programming/cpp/container.1649846422.txt.gz · Last modified: 2022/04/13 10:40 by odagawa