Your SlideShare is downloading. ×
C++によるソート入門
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

C++によるソート入門

2,047
views

Published on

C++において、どのようにソートを実装するかを、入門的に解説します。

C++において、どのようにソートを実装するかを、入門的に解説します。


0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
2,047
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. C++によるソート入門 Aiming 大阪スタジオ 後藤 文典
  • 2. 前篇関数インターフェースの移り変わり
  • 3. Cのインターフェース(1/2)void qsort( void *ptr, size_t count, size_t size, int(*comp)( const void *, const void * )); • 一応あらゆる型に対応できるけど・・・ • ×:型情報がない • ×:安全じゃない – 使う側が安全に呼んでくれるはず・・・ • ×:引数多い
  • 4. Cのインターフェース(2/2)void myqsort( void *ptr, size_t count, size_t size, int(*comp)( const void *, const void * )){ char *p = (char *)ptr; for(int i=0; i < n–1; i++) for(int j = n–1; j > i; j-- ){ char *rhs = p + (j * size); char *lhs = p + ((j-1) * size); if (comp(rhs, lhs) < 0) swap(rhs, lhs, size); } } myqsort(array, 10, sizeof(int), comp_int_less); myqsort(array, 10, sizeof(int), comp_int_greater);
  • 5. C++のインターフェース(1/2) ~ templateベース ~template < class It >void sort( It begin, It end );template< class It, class Cmp >void sort(It begin, It end, Cmp cmp);※It:Iterator※Cmp:Compare • ○:静的に型情報解決 – コンパイル成功 ≒ ちゃんと動く
  • 6. C++のインターフェース(2/2) ~ templateベース ~template < class It >void mysort(It begin, It end){ mysort(begin, end, myless<typename It::value_type>()); }template< class It, class Cmp >void mysort(It begin, It end, Cmp cmp) { It n_1 = end; n_1--; // 最後を指す for(It i=begin; i != n_1; ++i) for(It j=n_1; j != i; --j) { It j_1 = j; j_1--; if (cmp(*j, *j_1)) swap(*j, *j_1); }}mysort(vec.begin(), vec.end());mysort(vec.begin(), vec.end(), mygreater<int>());
  • 7. C++ & boostのインターフェース(1/2) ~ range-based algorithms ~template< class Range >Range &sort(Range &range);template< class Range, class Cmp >Range &sort(Range &range, Cmp cmp);• Boost.Rangeが代表 – STLの薄いラッパー• ○:引数がよりシンプルに• ○:可変長配列(vector等)と固定長配列の違いを 意識する必要がほとんど無い – 中で違いを吸収している
  • 8. C++ & boostのインターフェース(2/2) ~ range-based algorithms ~template< class Range >Range &mysort(Range &range) { std::sort(std::begin(range), std::end(range)); return range;}template< class Range, class Cmp >Range &mysort(Range &range, Cmp cmp) { std::sort(std::begin(range, std::end(range), cmp); return range;}mysort(vec)mysort(vec, mygreater<int>());
  • 9. C++11のインターフェース(1/2)~ rvalue reference & move semantics ~template< class Range >Range sort(Range range);template< class Range, class Cmp >Range sort(Range range, Cmp cmp);• ○:データの流れが使う側で分かる• ×:C++11未対応のコンパイラにソースを移植すると コピーコンストラクタだらけになってしまう ※rvalue referenceとmove semanticsについては後述
  • 10. C++11のインターフェース(2/2)~ rvalue reference & move semantics ~template< class Range >Range mysort(Range range) { std::sort(std::begin(range), std::end(range)); return range;}template< class Range, class Cmp >Range mysort(Range range, Cmp cmp) { std::sort(std::begin(range), std::end(range), cmp); return range;}vec = mysort(std::move(vec));vec = mysort(std::move(vec), mygreater<int>());
  • 11. 余談 良く分かる(かもしれない)rvalue reference & move semantics
  • 12. rvalue reference & move semantics(1/4)• rvalue reference(右辺値参照) – = の右っかわ • int型の値・クラスの一時オブジェクト• move semantics – rvalueを移動する – ○:コピーのコストが発生しない
  • 13. rvalue reference & move semantics(2/4)// move semanticsに対応したクラスclass Buffer { char *m_ptr; size_t m_size;public: Buffer(size_t size): m_size(size) { m_ptr = new char[size]; } Buffer(const Test &r): m_size(r.m_size) { { m_ptr = new char[r.m_size]; std::copy(r.m_ptr, r.m_ptr + r.m_size, m_ptr); } // ↓ムーブコンストラクタ Buffer(Test && r): m_ptr(r.m_ptr), m_size(r.m_size) { r.m_ptr = nullptr; } ~ Buffer() { delete[] m_ptr; }}
  • 14. rvalue reference & move semantics(3/4)class Buffer {public: Buffer(size_t size); Buffer(const Test &r); Buffer(Test && r); ~ Buffer();}Buffer buffer(1024);Buffer movedBuffer(std::move(buffer));//bufferは使えなくなる
  • 15. rvalue reference & move semantics(4/4)std::vector<int> makeTable(size_t size) { std::vector<int> vec(size); // 関数内の変数が戻り値になった場合は原則moveされる // ※C++11対応コンパイラの必要あり、 // 未対応だとコピーされる return vec;}std::vector<int> vec = makeTable(1024);
  • 16. 前編の参考資料• Boost.Range入門 – http://www.slideshare.net/egtra/boostrange• rvalue reference完全入門 – http://cpplover.blogspot.jp/2009/11/rvalue- reference_23.html• 暗黙のmoveとNRVO – http://d.hatena.ne.jp/joynote/20110822/1314012953
  • 17. 後編ソートのアルゴリズム
  • 18. ソート• データの集合を一定の規則に従って並べること• 大抵値の昇順か降順
  • 19. ソートで使われる用語• ソートの結果 – 安定ソート • 同じ値に関して、ソート前の順序が維持されている – 安定でないソート • 同じ値に関して、ソート前の順序が維持される保証が無い• ソートのコスト – 平均計算時間 • 最悪 ~ 最良の計算時間の平均 – 最悪計算時間 • そのソートが最も苦手とするデータ並び時のソート時間 – メモリ使用量 • ソート時に使用されるメモリ量
  • 20. 色々なソートアルゴリズム(1/2)• クイックソート – ○:平均計算時間はソートアルゴリズムの中でも速い方 – ×:最悪計算時間がO(n~2)とかなり遅い• ヒープソート – ○:メモリ効率が良い – ×:並列化出来ない• イントロソート – クイックソートとヒープソートの混成 – 最初はクイックソート、途中からヒープソートに切り替え – ○:クイックソートの最悪計算時間を克服
  • 21. 色々なソートアルゴリズム(2/2)• マージソート – ○:安定ソート、並列化しやすい – ×:メモリ食い – 速度はそこそこ• In-placeマージソート – マージソートとクイックソートの混成 – 基本はマージソートで、途中でクイックソート的な事をする – ○:メモリ効率が良い – Web巡回する限り速くないけど遅くも無いという印象• 挿入ソート – ○:アルゴリズム単純、整列済み配列への挿入が高速 – 単体で使う事はあまりない、他のソートの部品として使う• Etc
  • 22. ソートの選び方• 例えば – とあるスプライト群をZソートしたい • クイックソートを選択 – ×:プレイ中にいきなり重くなる?! – 最悪計算時間はO(n~2)なので、 データが最悪計算時間がかかる並びになってしまった – マルチスレッドで並列化したい • ×:ただ闇雲にスレッドセーフにしただけでは、 lock, unlockのオーバーヘッドでかえって遅くなる • データをスレッド数で分割し、それぞれを イントロソートやマージソートでソート後、 最後にマージソートや挿入ソートをする等の工夫をする• 状況や扱うデータ、使えるメモリ等によって使い分ける
  • 23. 後編の参考資料• Wikipedia ソート – http://ja.wikipedia.org/wiki/ソート• 要素数が少ない場合のソートベンチマーク – http://www.moon.sannet.ne.jp/okahisa/sort/node38.html• ソートアルゴリズムについて考える – http://d.hatena.ne.jp/junjun777/20120821