Upload
tomohiro-namba
View
62
Download
0
Embed Size (px)
Citation preview
C++ For Researchers 研究生のためのC++
企画・立案 難波知宏
STL (Standard Template Library)
第五回
2
3
目次
1. コンテナの考え方
コンテナとは
2. STLのコンテナ
可変長配列
線形リスト
集合
写像
その他
3. コンテナのアルゴリズム
イテレータについて
範囲forとfor_each
全要素に対する□□
コンテナの考え方
第一節
4
• 連結リスト、連想配列、スタック、キュー、etc…
• 配列もコンテナの一種
5
コンテナ
オブジェクトの集合を表すもの
Container Object
Object
Object Object
Object
6
STL (Standard Template Library)
テンプレートを駆使したライブラリ、コンテナの実装も含む
コンテナ
固定長配列
可変長配列
線形リスト
集合
写像(連想配列)
スタックとキュー
優先度付きキュー
アルゴリズム
ソーティング
検索
走査
etc...
STLのコンテナ
第二節
7
vector<T>
8
可変長配列
• メモリ上に連続して要素を格納
• メモリ効率が良い
• アクセス速度が速い
• 挿入などの処理で容量が足りなく
なると、メモリを再確保する
9
ランダムアクセス 𝑶(𝟏)
挿入/削除 𝑂(𝑛)
検索 𝑂(𝑛)
可変長配列
可変長配列 要素数を実行中に変えられる配列
size (3)
capacity(5)
vector<T>
list<T>
10
リスト
• ランダムアクセス/検索は遅い(先頭からいちいちたどらないといけな
い)
• 挿入・削除操作に強い
11
ランダムアクセス 𝑂(𝑛)
挿入/削除 𝑶(𝟏)
検索 𝑂(𝑛)
リスト
線形リスト 各要素をポインタで接続する
list<T>
set<T>
12
集合/セット
• 検索に強い
• 多くの場合、平衡二分探索木で
実装されている
• 自動でソートされる
13
ランダムアクセス ×
挿入/削除 𝑶(𝒍𝒐𝒈(𝒏))
検索 𝑶(𝒍𝒐𝒈(𝒏))
集合/セット
集合 要素の集合を表す
set<T>
map<K,V>
14
写像/マップ
• 検索に強い
• 多くの場合、平衡二分探索木で
実装されている
• キー順に自動でソートされる
15
ランダムアクセス 𝑶(𝒍𝒐𝒈(𝒏))
挿入/削除 𝑶(𝒍𝒐𝒈(𝒏))
検索 𝑶(𝒍𝒐𝒈(𝒏))
写像/マップ
写像 キーと値のペアを保持し、キーで要素にアクセスできる
map<T>
コンテナのアルゴリズム
第三節
16
17
コンテナの走査がしたい
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
19
リストや二分木は、メモリ上に要素が連続して
いない
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 ポインタ方式ではアクセス不可
21
そこでイテレーターの登場
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用のイテレーター
• データ構造に合わせて、++演算子をオーバーロードしている
例)vectorなら単純にアドレスを加算
listならポインタに従って次の要素に移動
• ->演算子や*演算子をオーバーロードしているので
ポインタと同じ感覚で使える
23
イテレーターのからくり
統一のインターフェース
による走査が可能
24
イテレーターによるループの欠点:
イテレーターの型名が長い
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 に格納される
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とラムダ式
コンテナに対し、各要素に対して何をさせるかを定義した関数を渡し
て処理する
[](…){…}
でここだけで使用する関数を定義 (ラムダ式)
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
条件を満たす(最初の)要素の イテレーターの取得