データの集まりをコード・アルゴリズム上で扱いやすくするため、API やメモリ上の配置方法をまとめたもの
「アルゴリズム + データ構造 = プログラム」
ちょっと古い主張だが…
次のような計算を考える
for (i = 0; i < n; i ++) {
for (j = 0; j < n; j++) {
c[i][j] = a[i] * b[j];
}
}
これをビッグオー記法にすると、
大きい項だけ残す
大きければ性能が悪い
計算量 | 例 |
---|---|
O(1) | ArrayList から値の取り出し |
O(log N) | 二分木の探索 |
O(N) | 単純なループ |
O(N log N) | クイックソート |
O(N ^ 2) | 2重ループ |
O(N!) | N 個すべての組み合わせの列挙 |
size() | リストの長さ n を返す |
get(i) | i 番目の要素を返す |
set(i, x) | i 番目の要素を x にする |
add(i, x) | x を i 番目に追加し、以降を後ろにずらす |
remove(i) | i 番目の要素を削除し、以降を前にずらす |
a
c
d
size() | O(1) |
get(i) | O(1) |
set(i, x) | O(1) |
add(i, x) | O(n-i) |
remove(i) | O(n-i) |
a
b
c
d
a
b
c
c
d
a
b
e
c
d
i 以降のコピー
i への代入
a
b
c
d
a
b
e
c
d
元の配列からコピー
i への代入
d
c
a
b
新しい配列の生成
d
c
a
b
resize あり
単方向連結リスト
双方向連結リスト
size() | O(1) |
get(i) | O(min{i, n-i}) |
set(i, x) | O(min{i, n-i}) |
add(i, x) | O(min{i, n-i}) |
remove(i) | O(min{i, n-i}) |
add(x) | 要素を追加 |
find(x) | 要素があるかどうか確認する |
get(x) | 対応する要素を取得 |
remove(x) | 要素を削除 |
オブジェクトのハッシュ値を計算し対応する場所に入れる
array<TableCell> t;
int n;
bool add(T x) {
if (find(x) != null) return false;
if (n+1 > t.length) resize();
t[hash(x)].add(x);
n++;
return true;
}
ハッシュ値が衝突した場合どうするか?
hash(x) となる要素が既にあった場合には、テーブルを線形に探索 = 1 つずつずらしながら空いている場所を探す
find(x) | O(1) |
get(x) | O(1) |
remove(x) | O(1) |
かなり理想的な想定
深さ
(depth)
葉
(leaf)
根
(root)
親
(parent)
子
(child)
6
4
1
5
10
8
find(x) | O(log n) |
get(x) | O(log n) |
remove(x) | O(log n) |
6
8
4
1
など
アルゴリズム(次回)
ネットワーク