More Related Content
More from Kenta Hattori (20)
アルゴリズムとデータ構造3
- 3. 2011/4/19 アルゴリズムとデータ構造 3 3
Python の拡張
本講義で使用する手続き, record, array,
error を Python から使えるように定義してお
く
方法:
extension.py を python32libsite-packages にコ
ピーする
インタプリタから以下を入力する
>>> from extension import *
- 4. 2011/4/19 アルゴリズムとデータ構造 3 4
列の表現
列は値の順序づけられた並び
例: <1,2,3,4,5>, <59,23,43>
要素の順序に意味がある
例: <1,2,3> と <2,3,1> は異なる列である
Cf. 集合 (Set)
基本的な操作
挿入:列に要素を挿入する
削除:列中の特定の要素を削除する
参照:列中の特定の要素のデータを読み書きする
- 5. 2011/4/19 アルゴリズムとデータ構造 3 5
配列による列の表現
特徴
配列は通常,最大の要素数 ( 配列のサイズ ) が固定されている
配列のサイズを超えて,要素を格納することはできない
列の要素は,インデックスを指定して参照することができる.
インデックスは 0 はじまりの流儀と, 1 はじまりの流儀があるので注意.
インデックスを指定しての配列の要素参照は O(1) の計算量
例:サイズ size ,要素数 k の列.(配列版)
先頭から順に要素を詰めておく
配列版の列を作成する関数 seq_array(sz) は補足資料
(extension3.py) 参照
23 10 5A
0 1 2 size-1Index:
55
k-1
3 ・・・
k
・・・
- 6. 2011/4/19 アルゴリズムとデータ構造 3 6
列(配列版)へのデータ挿入
列(配列版) SA の k 番目に,要素 x を挿入する
def seq_array_insert(SA, k, x):
if k > SA.length or k < 0: error(“out of range”)
if SA.length >= len(SA.elems): error(“size over”)
for i in range(SA.length, k, -1):
SA.elems[i] = SA.elems[i-1]
SA.length = SA.length + 1
SA.elems[k] = x
for 文で,列の後ろからデータを 1 つずつずらしていき,要素を
挿入する場所を空ける.
23 10 5elems 55 3 ・・・・・・
k0
・・・
length-1 len(elems)-1
23 10 5 55 ・・・・・・
0
・・・
len(elems)-1
3elems
- 7. 2011/4/19 アルゴリズムとデータ構造 3 7
列(配列版)からのデータ削除
列(配列版) SA から k 番目の要素を削除する
def seq_array_delete(SA, k):
if k < 0 or k >= SA.length: error(“out of range”)
for i in range(k, SA.length-1):
SA.elems[i] = SA.elems[i+1]
SA.length = SA.length - 1
挿入とは逆に,削除する点から後ろのデータを 1 つずつ前にず
らして,穴をふさいでいく
問題:
要素数 N の配列で,挿入,削除にかかる最悪計算量はどれくらいか?
23 10 5elems 55 3 ・・・・・・
k0
・・・
length-1 len(elems)-1
ゴミが残る
ことに注意
- 8. 2011/4/19 アルゴリズムとデータ構造 3 8
練習問題
列(配列版)の要素を逆順にする
seq_array_reverse のコードを書け.
def seq_array_reverse(SA):
… 配列 SA.elems の要素を逆順に並びか
える.
- 10. 2011/4/19 アルゴリズムとデータ構造 3 10
連結リストによる列の表現
連結リスト
値と次のオブジェクトをさすポインタから構成される複合データが数珠繋ぎになっているよ
うなデータ構造
リスト L の k 番目のノードを返す
def seq_list_search(L, k):
n = L.head
i = 0
while n != None and i != k:
n = n.next
i = i + 1
return n
リスト版の列を作成する関数 seq_list() ,ノードを作成する関数 node() の
定義は,補足資料 (lecture3.py) 参照
問題: k がリストの要素数を超えていた場合,上記コードは何が返るか?
L.head nextelem
25 9 16 4 1
リストのノー
ド
ノードを先頭から
順番に辿っていく
- 11. 2011/4/19 アルゴリズムとデータ構造 3 11
連結リストによる列の表現(2)
ノード n の後ろへ要素 x を挿入する
def seq_list_insert_after(n, x):
m = node() # 新しいノードを作成
m.elem = x
m.next = n.next
n.next = m
問題:挿入の計算量はどれくらいか?
L.head nextelem
25 9 16 4 1
99
m
n
- 12. 2011/4/19 アルゴリズムとデータ構造 3 12
連結リストによる列の表現(3)
リストの先頭へ挿入
def seq_list_insert_head(L, x):
n = node()
n.elem = x
n.next = L.head
L.head = n
L.head nextelem
25 9
x
n
- 15. 2011/4/19 アルゴリズムとデータ構造 3 15
連結リストによる列の表現(4)
要素の後ろを削除
ノード n の次の要素を削除する.
def seq_list_delete_after(n):
m = n.next
n.next = m.next
# m の領域を解放する (Python では不要 )
問題:
後ろではなく,渡された要素そのものを削除する
ことはできるか?
- 16. 2011/4/19 アルゴリズムとデータ構造 3 16
二重連結(双方向)リスト
前の要素を指すポインタも持たせる.
リストの先頭への要素 x を挿入
def seq_dlist_insert_head(L, x):
n = dnode()
n.elem = x
n.next = L.head
if L.head != None:
L.head.prev = n
L.head = n
n.prev = None
L.head nextelem
25 9 16 4 1
prev
- 17. 2011/4/19 アルゴリズムとデータ構造 3 17
二重連結(双方向)リスト(2)
問題: 2 重連結リスト版の
seq_dlist_insert_after(n,x) を書け
ノード n の削除
def seq_dlist_delete(L, n):
if n.prev != None:
n.prev.next = n.next
else:
L.head = n.next
if n.next != None:
n.next.prev = n.prev
- 18. 2011/4/19 アルゴリズムとデータ構造 3 18
番兵( Sentinel )
seq_dlist_delete は,もし,リストの先頭と末尾に
関する境界条件を無視すれば,より簡単に書ける.
def seq_dlist_with_sentinel_delete(n):
n.prev.next = n.next
n.next.prev = n.prev
番兵( sentinel )は境界条件を簡単化するためのダ
ミーのオブジェクトである.
循環二重連結リスト
L.head
L.head
9 16 4
- 19. 2011/4/19 アルゴリズムとデータ構造 3 19
配列によるリストの実現
右図のように2つの配列を
用いて,リストを実現する
こともできる.
問題:
右図の表現に対応した
seq_arrlist_search(L,k) を書
け
25 2
9
016
1
4 4
1 -1
L.elems[0]
[1]
[2]
elems
[3]
[4]
nexts
0L.head
L.nexts[0]
[1]
[2]
[3]
[4]