27
C++ For Researchers 研究生のためのC++ 企画・立案 難波知宏

研究生のためのC++ no.5

Embed Size (px)

Citation preview

Page 1: 研究生のためのC++ no.5

C++ For Researchers 研究生のためのC++

企画・立案 難波知宏

Page 2: 研究生のためのC++ no.5

STL (Standard Template Library)

第五回

2

Page 3: 研究生のためのC++ no.5

3

目次

1. コンテナの考え方

コンテナとは

2. STLのコンテナ

可変長配列

線形リスト

集合

写像

その他

3. コンテナのアルゴリズム

イテレータについて

範囲forとfor_each

全要素に対する□□

Page 4: 研究生のためのC++ no.5

コンテナの考え方

第一節

4

Page 5: 研究生のためのC++ no.5

• 連結リスト、連想配列、スタック、キュー、etc…

• 配列もコンテナの一種

5

コンテナ

オブジェクトの集合を表すもの

Container Object

Object

Object Object

Object

Page 6: 研究生のためのC++ no.5

6

STL (Standard Template Library)

テンプレートを駆使したライブラリ、コンテナの実装も含む

コンテナ

固定長配列

可変長配列

線形リスト

集合

写像(連想配列)

スタックとキュー

優先度付きキュー

アルゴリズム

ソーティング

検索

走査

etc...

Page 7: 研究生のためのC++ no.5

STLのコンテナ

第二節

7

Page 8: 研究生のためのC++ no.5

vector<T>

8

可変長配列

Page 9: 研究生のためのC++ no.5

• メモリ上に連続して要素を格納

• メモリ効率が良い

• アクセス速度が速い

• 挿入などの処理で容量が足りなく

なると、メモリを再確保する

9

ランダムアクセス 𝑶(𝟏)

挿入/削除 𝑂(𝑛)

検索 𝑂(𝑛)

可変長配列

可変長配列 要素数を実行中に変えられる配列

size (3)

capacity(5)

vector<T>

Page 10: 研究生のためのC++ no.5

list<T>

10

リスト

Page 11: 研究生のためのC++ no.5

• ランダムアクセス/検索は遅い(先頭からいちいちたどらないといけな

い)

• 挿入・削除操作に強い

11

ランダムアクセス 𝑂(𝑛)

挿入/削除 𝑶(𝟏)

検索 𝑂(𝑛)

リスト

線形リスト 各要素をポインタで接続する

list<T>

Page 12: 研究生のためのC++ no.5

set<T>

12

集合/セット

Page 13: 研究生のためのC++ no.5

• 検索に強い

• 多くの場合、平衡二分探索木で

実装されている

• 自動でソートされる

13

ランダムアクセス ×

挿入/削除 𝑶(𝒍𝒐𝒈(𝒏))

検索 𝑶(𝒍𝒐𝒈(𝒏))

集合/セット

集合 要素の集合を表す

set<T>

Page 14: 研究生のためのC++ no.5

map<K,V>

14

写像/マップ

Page 15: 研究生のためのC++ no.5

• 検索に強い

• 多くの場合、平衡二分探索木で

実装されている

• キー順に自動でソートされる

15

ランダムアクセス 𝑶(𝒍𝒐𝒈(𝒏))

挿入/削除 𝑶(𝒍𝒐𝒈(𝒏))

検索 𝑶(𝒍𝒐𝒈(𝒏))

写像/マップ

写像 キーと値のペアを保持し、キーで要素にアクセスできる

map<T>

Page 16: 研究生のためのC++ no.5

コンテナのアルゴリズム

第三節

16

Page 17: 研究生のためのC++ no.5

17

コンテナの走査がしたい

Page 18: 研究生のためのC++ no.5

sample 5-01

#include <iostream>

using std::cout;

int main()

{

int a[4] = { 1,2,3,4 };

for (int i = 0; i < 4; i++)

cout << a[i] << ' ';

}

sample 5-02

#include <iostream>

using std::cout;

int main()

{

int a[4] = { 1,2,3,4 };

for (int* p = a; p != a + 4; p++)

cout << *p << ' ';

}

18

iteration

走査

従来の配列の走査

ポインタを使ってアクセス (先頭からのオフセットでアクセス)

a[i] p

Page 19: 研究生のためのC++ no.5

19

リストや二分木は、メモリ上に要素が連続して

いない

Page 20: 研究生のためのC++ no.5

sample 5-01

#include <iostream>

using std::cout;

int main()

{

int a[4] = { 1,2,3,4 };

for (int i = 0; i < 4; i++)

cout << a[i] << ' ';

}

sample 5-02

#include <iostream>

using std::cout;

int main()

{

int a[4] = { 1,2,3,4 };

for (int* p = a; p != a + 4; p++)

cout << *p << ' ';

}

20

iteration

走査

配列の走査

ポインタを使ってアクセス (先頭からのオフセットでアクセス)

a[i] p ポインタ方式ではアクセス不可

Page 21: 研究生のためのC++ no.5

21

そこでイテレーターの登場

Page 22: 研究生のためのC++ no.5

22

イテレーター

ポインタの概念を、データ構造に合わせて拡張したもの

list<int> v = { 1,2,3,4 };

for (list<int>::iterator it = v.begin(); it != v.end(); it++)

{

cout << *it << ' ';

}

vector<int> v = { 1,2,3,4 };

for (vector<int>::iterator it = v.begin(); it != v.end(); it++)

{

cout << *it << ' ';

}

sample 5-03

sample 5-04

vector用のイテレーター

list用のイテレーター

Page 23: 研究生のためのC++ no.5

• データ構造に合わせて、++演算子をオーバーロードしている

例)vectorなら単純にアドレスを加算

listならポインタに従って次の要素に移動

• ->演算子や*演算子をオーバーロードしているので

ポインタと同じ感覚で使える

23

イテレーターのからくり

統一のインターフェース

による走査が可能

Page 24: 研究生のためのC++ no.5

24

イテレーターによるループの欠点:

イテレーターの型名が長い

Page 25: 研究生のためのC++ no.5

vector<int> v = { 1,2,3,4 };

for (auto it = v.begin(); it != v.end(); it++)

{

cout << *it << ' ';

}

sample 5-06

vector<int> v = { 1,2,3,4 };

for (int x : v)

{

cout << x << ' ';

}

25

範囲for文

範囲for文

イテレーターによる走査を簡略化した記法

auto x = …

で自動で型決定 (≠なんでも格納できる変数)

for (Type var : container) { … }

でcontainerの各要素が変数var に格納される

Page 26: 研究生のためのC++ no.5

vector<int> v = { 1,2,3,4 };

for (auto it = v.begin(); it != v.end(); it++)

{

cout << *it << ' ';

}

sample 5-07

vector<int> v = { 1,2,3,4 };

for_each(v.begin(), v.end(), [](int x) { cout << x << ' '; });

26

for_each

for_eachとラムダ式

コンテナに対し、各要素に対して何をさせるかを定義した関数を渡し

て処理する

[](…){…}

でここだけで使用する関数を定義 (ラムダ式)

Page 27: 研究生のためのC++ no.5

sample 5-08

list<int> v = { 1,2,3,4,5 };

// 条件に合う要素を削除する

v.remove_if([](int x) { return x < 3; });

for (auto& x : v)

cout << x << ' ';

cout << endl;

// 条件に合う要素を検索する

auto it = find_if(v.begin(), v.end(), [](int x) { return x > 4; });

cout << *it << endl;

27

ラムダ式とSTLの合わせ技

実行結果

3 4 5

5

remove_if

条件を満たす要素を削除

find_if

条件を満たす(最初の)要素の イテレーターの取得