アルゴリズムとデータ構造 1章の復習 第2章 リスト構造 5月10日

Slides:



Advertisements
Similar presentations
アルゴリズムとデータ構造 第 1 章 アルゴリズムと計算量 5 月 6 日 情報知能学科 白井英俊.
Advertisements

アルゴリズムと データ構造 第 3 回 基本的なデータ構造(2) : 配列 1. 前回の復習 アルゴリズムの計算量 最悪(最大)計算量 計算量の漸近的評価 (オーダ)  多項式時間アルゴリズム( polynomial time algorithm )  指数時間アルゴリズム( exponential.
アルゴリズムと データ構造 第 2 回 アルゴリズムの計算量 基本的なデータ構造(1). 前回の復習(1) アルゴリズムの数学的定義  チューリングマシンで記述可能な手続きをアルゴリズムと呼ぶ データ構造とは  データをコンピュータの記憶部分に組織化して格納する表現方 法 プログラムとは  プログラムはデータ構造を利用して,アルゴリズムをプログラ.
アルゴリズムとデータ構造 第2回 線形リスト(復習).
Generic programming と STL
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
プログラミング基礎I(再) 山元進.
プログラミング言語としてのR 情報知能学科 白井 英俊.
~手続き指向からオブジェクト指向へ(Ⅰ)~
第13回構造体.
プログラミングパラダイム さまざまな計算のモデルにもとづく、 プログラミングの方法論 手続き型 関数型 オブジェクト指向 代数 幾何.
データ構造とアルゴリズム 第10回 mallocとfree
第12回構造体.
アルゴリズムとデータ構造 第2章 リスト構造 5月17日分
数値計算及び実習 第3回 プログラミングの基礎(1).
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
アルゴリズムとデータ構造1 2007年6月12日
アルゴリズムとデータ構造 第1章 アルゴリズムと計算量 4月26日
2009/10/9 良いアルゴリズムとは 第2講: 平成21年10月9日 (金) 4限 E252教室 コンピュータアルゴリズム.
アルゴリズムとデータ構造 第3回基本的なデータ構造(リスト) 2015/10/28 アルゴリズムとデータ構造 2015.
データ構造と アルゴリズム 第二回 知能情報学部 新田直也.
C言語講座 第4回 ポインタ.
情報科学1(G1) 2016年度.
第6章 2重ループ&配列 2重ループと配列をやります.
岩井 儀雄 コンピュータ基礎演習  ー探索、整列ー 岩井 儀雄
データ構造と アルゴリズム 第四回 知能情報学部 新田直也.
第3回 配列,構造体,ポインタ ~ データ構造について学ぶための基礎~
C言語講座 第3回 ポインタ、配列.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
Cプログラミング演習 第7回 メモリ内でのデータの配置.
アルゴリズムとデータ構造1 2006年6月16日
プログラミング 4 記憶の割り付け.
プログラミング言語入門.
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
情報とコンピュータ 静岡大学工学部 安藤和敏
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
アルゴリズムとデータ構造 第3章 ヒープ 6月10日分
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
VBで始めるプログラミング こんにちは、世界。 /28 NARC.
アルゴリズムとデータ構造 はじめに 第1章 アルゴリズムと計算量
アルゴリズムとデータ構造 第1章 アルゴリズムと計算量 4月15日
情報処理Ⅱ 第2回:2003年10月14日(火).
プログラミング 4 探索と計算量.
オブジェクト・プログラミング 第8回.
アルゴリズムとデータ構造 2011年7月8日課題の復習
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
構造体と共用体.
情報とコンピュータ 静岡大学工学部 安藤和敏
データ構造とアルゴリズム 第11回 リスト構造(1)
アルゴリズムとデータ構造 第2章 リスト構造 5月20日分
アルゴリズムとデータ構造 第3章 ヒープ 5月31日分
アルゴリズムとデータ構造 第3章 ヒープ 5月31日分の復習
アルゴリズムとプログラミング (Algorithms and Programming)
補講:アルゴリズムと漸近的評価.
データ構造とアルゴリズム (第5回) 静岡大学工学部 安藤和敏
アルゴリズムからプログラムへ GRAPH-SEARCH
ポインタとポインタを用いた関数定義.
アルゴリズムとデータ構造1 2009年6月15日
アルゴリズムとデータ構造 第2章 リスト構造 5月24日分
オブジェクト指向言語論 第二回 知能情報学部 新田直也.
データ構造とアルゴリズム論 第9章 連結リスト
プログラミング 4 文字列.
アルゴリズムとデータ構造 2010年6月17日
ソフトウェア工学 知能情報学部 新田直也.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
参考:大きい要素の処理.
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
Presentation transcript:

アルゴリズムとデータ構造 1章の復習 第2章 リスト構造 5月10日 アルゴリズムとデータ構造 1章の復習 第2章 リスト構造 5月10日 情報知能学科 白井英俊 1

計算量:時間と空間 時間計算量、もしくは時間複雑度(time complexity) そのアルゴリズムを実行するのに、最悪の場合、どのくらい時間がかかるかを、入力の大きさの関数として表す 空間計算量、もしくは空間複雑度(space complecity)    そのアルゴリズムを実行するのに、最悪の場合、どのくらい記憶領域が必要かを、入力の大きさの関数として表す 計算量(複雑度)=時間計算量+空間計算量 2

時間計算量の常識的な評価 教科書p.8 O(1) --- 理想的に速い O(log n) --- 非常に速い O(n) --- 速い O(n log(n)) --- 速いほう O(n2) --- かなり遅いが、許されないほどではない O(n3) --- かなり遅い。許される限界。 O(cn ) --- (cは1より大きい定数)。指数オーダ(exponential order)。とっても遅い。 3

計算量の演習1 教科書p.11 1.1 次の5種類の計算時間を、nを横軸にとって、一つのグラフに重ねて表せ。そして、そのグラフからオーダの大小関係が読み取れることを観察せよ。 f1(n) = 10000 n f2(n) = 10000 n log(n) f3(n) = 100 n**2 f4(n) = 10 n**3 f5(n) = 2**n 実際にグラフを書く前に、 これらのオーダがどうなるか 考えておいてください 4

計算量の演習1の解答 GnuPlotを用いる。ただし、xをnと「読み替える」 (1≦x≦30 のグラフ。x=30では f5 > f2 > f1 > f4 > f3のように見えるが…)

計算量の演習1の解答(続) f5を除いて3000まで表示させると、 f4 > f3 > f2 > f1 となる ことが分かる

計算量の演習1 の解答(まとめ) つまり、nが十分大きければ、       n < n*log(n) < n2 < n3 < 2n であることが分かる f1(n) = 10000 n    オーダ:O(n) f2(n) = 10000 n log(n) O(n log(n)) f3(n) = 100 n**2 O(n2 ) f4(n) = 10 n**3 O(n3 ) f5(n) = 2**n O(2n ) 7

計算量の演習2 教科書p.11 1.2 ステップ数が f(n)=100000n, g(n)=10n**3, h(n)=2**nの3つのアルゴリズムにn=100の大きさのデータを与えたとする。1ステップが10**(-9)秒で実行できるコンピュータで走らせたときの計算時間は次のどれに近いか? 1ミリ秒、1秒、1分、1時間、1日、1ヶ月、1年、1世紀 8

計算量の演習2の解答 問題:ステップ数がf(n)=100000n, g(n)=10n**3, h(n)=2**nの3つのアルゴリズムにn=100の大きさのデータを与えたとする。 1ステップが10**(-9)秒で実行できるコンピュータで走らせたときの計算時間は? 答え: f(100)=100000*100 = 107 g(100)=10*100**3 =107 1ステップが10-9秒なので、f もgも107*10-9 =1*10-2秒 (10ミリ秒) h(100)=2**(100) ≒ 1030 1ステップが10-9秒なので、h(100)*10-9 ≒ 1030*10-9 =1*1021秒 1年=60*60*24*365≒ 3.2*107 秒, 1世紀=100年=3.2*109秒 210 =1024 ≒103  だから2100=(210)10= (103)10

計算量の演習3 教科書p.11 1.4 次の式のオーダを、最も忠実で簡単な式を用いて表せ。 (1) 6.5n3 + 8n2 + 5 (2) 5 n log(n) + 3 n2 (3) 2.5 n √n + 3.6 n log(n) (4) 5 n + 8 log(n) (5) 2n + 5 n 5 (6) 800 n log(n) + n 10

計算量の演習3の解答 問題: 次の式のオーダを、最も忠実で簡単な式を用いて表せ。 (1) 6.5n3 + 8n2 + 5 問題: 次の式のオーダを、最も忠実で簡単な式を用いて表せ。 (1) 6.5n3 + 8n2 + 5 (2) 5 n log(n) + 3 n2 (3) 2.5 n √n + 3.6 n log(n) (4) 5 n + 8 log(n) (5) 2n + 5 n 5 (6) 800 n log(n) + n 注意:2nのような「2」は定数倍ではない。nの関数に『掛け算』されている『数』が無視の対象 解法: (1)定数倍を無視 (2)最も大きくなるnの項だけを残す

計算量とオーダ ここまでで何か質問は? アルゴリズムが与えられた時に、『計算量』を求めることは、5章に入ったら…

4月の講義のまとめ 「アルゴリズム」 「アルゴリズム」の計算量 時間複雑度、空間複雑度 オーダ : log(n), n, n*log(n),n**2, n**3, 2**n, n! 「アルゴリズム」をプログラムとして実現することにより、アルゴリズムの検証を行う ー プログラムを書くだけではなく、いろいろな例で実験する そのために、Rubyの復習が必要(代入、条件分岐、繰り返し、変数/定数、配列、クラス) アルゴリズムをプログラムとして実現する 再帰関数:プログラムを書く、プログラムを読む(動きを追う)

アルゴリズムの例 入力 出力 問題(教科書p.1): n個の実数x1, x2, …, xnが与えられて、その中の最大値を求める

アルゴリズムの例(続) 最低限、このように書けるようになろう! より明確な記述(p.2) 入力: 正の整数nとn個の実数値x1, x2, …, xn  出力: x1, x2, …, xnの中の最大値  手続き: 1. y ← x1 (yは「それまでの最大値」を記録) 2. i = 2,3,…,nに対して順に次を行う:    xi > y ならば y ← xi 3. yを出力する 「変数y に x1の値を代入する」

アルゴリズムの例(続) このような記法のアルゴリズムから プログラムを実現できるように! 「プログラム」風(p.3) MAXはアルゴリズムの名前。カッコのなかは入力「引数」を書く。 「プログラム」風(p.3) Algorithm MAX(n, x1, x2, …, xn): 入力(Input): 正整数 n と n 個の実数x1, x2, …, xn 出力(Output): x1, x2, …, xnの中の最大値 手続き(Procedure):   1. y ← x1 ; 2. for i ← 2 until n do    if xi > y then y ← xi ; 3. return y; ここでの記法についてはウェブページの「教科書のアルゴリズムの記述とRUBY言語の対応」参照 このような記法のアルゴリズムから プログラムを実現できるように!

新しい概念:ポインタ(pointer) ポインタの元々の意味は「指さし」。 「変数」の役割は、 「オブジェクトを指す」  (オブジェクトを「値」として持っているわけではない)   例えば、変数xに配列[1,2,3] を代入したとする。   その結果、「変数」の値として配列[1,2,3]が入るのではなく、配列そのものは別の場所に作られ、その場所への『手がかり』が「変数の値」になる。    このような手がかり(記憶番地、アドレス)をポインタという。    Rubyの変数の『値』は、みなポインタ 参考: プログラミング言語Cでは、int *x のように書いて、変数xは、整数オブジェクトへのポインタ(アドレス)を値とする、というように宣言する 17

ポインタの詳細 記憶場所b 記憶場所a 変数名 x アドレス(記憶番地):コンピュータの記憶場所  ここでは少し拡張して「データの格納場所の手がかり」(場所の情報)と考える 例: 配列を変数に代入 記憶場所b 記憶場所a 変数名 配列:かなりの場所を必要とする複雑なデータ x アドレス 18

ポインタによる説明 5 [ , 3 ] 1, 2 x = [1, 2, 3] x y = x x[1] = 5 y コンピュータの内部: x = [1, 2, 3] x xの記憶場所 y = x 5 x[1] = 5 y yの記憶場所 p y => [1,5,3] x.shift [ , 3 ] 1, 2 配列: p y => [5, 3] 注意:本当は「配列」は、かなり複雑な形をしているのだけど、簡略化しています

クラスとインスタンス Rubyのオブジェクトには 数、文字列、配列、…などがあった これは、プログラミング言語としてはかなり豊か  数、文字列、配列、…などがあった これは、プログラミング言語としてはかなり豊か これらを使いこなせば、いろいろなことができる。でも… 問題に適したデータ構造を考えないといけないことがある。 そのために、クラス定義とインスタンス生成の方法は知っておかないといけない (本講義では これから多用します) 20

Rubyにおけるクラス定義 オブジェクト指向 プログラムが扱うデータ(オブジェクト)と、それをどのように扱うかという手続き(関数)とを「組」として表す クラスーオブジェクトの「種類」 クラス定義 1) どのようなパーツ(部品)があるかを宣言:インスタンス変数   2) 手続き(関数)の宣言:インスタンスメソッド

クラス定義の例 部品名 名簿の一つの項目を「クラス」として定義する 名簿の項目(Item)には、(少なくとも)次のパーツ(部品)をもつと考えられる 1)名前  2)住所 3)生年月日 4)性別 5)年齢 name address birth_date sex age これを図示すると… クラス名 Item name address birth_date sex age 具体的な値がはいる(ポインタ) 部品名

クラス定義の例(続) 右に図示した名簿の項目(Item)に対応した「クラス」: Item class Item   def initialize(n,a,b,s) @name = n @address = a @birth_date = b @sex = s @age = Time.now.year - b end Item name address birth_date sex age 大文字から始める Initialize は重要なインスタンスメソッド。「インスタンス」作成の時に説明 @つきの変数が「インスタンス変数」 これが「パーツ(部品)名」になる

クラス定義の例(続) ただ、このままだと、部品にアクセス(取り出し、参照)しにくいので… class Item def initialize(n,a,b,s) @name = n @address = a @birth_date = b @sex = s @age = Time.now.year - b end attr_accessor :name, :address, :birth_date, :sex, :age Item name address birth_date sex age attr_accessor につづけて インスタンス変数名の前にコロン( : )

インスタンス生成 鯛焼きを食べるには、「材料を用意して、鯛焼きを作る」必要がある。 それをするのが、「インスタンス生成」   インスタンス生成 鯛焼きに例えて言えば、 クラス定義は、鯛焼きを焼く金型(鉄板) これだけでは、鯛焼きは食べられない… 鯛焼きを食べるには、「材料を用意して、鯛焼きを作る」必要がある。 それをするのが、「インスタンス生成」 「Taro Yamada」の名簿項目を作る:   Item.new(“Taro Yamada”, “Toyota”, 1990, “male”) 注:ここでは、生年月日ではなく「生まれた年(西暦)」としよう

インスタンス生成(続) Item.new (“Taro Yamada”, “Toyota”,1990, “male”) これにより、initializeメ ソッドが呼び出される class Item def initialize(n, a, b, s) @name = n @address = a @birth_date = b @sex = s @age = Time.now.year - b end attr_accessor :name, :address, :birth_date, :sex, :age その引数の n, a, b, sがそれぞれ Item.new の実引数と結び付けられ、 次に  の文が実行 されて、次に示すようなItemクラスのインスタンスができあがる:

インスタンス生成(完成) Item.new(“Taro Yamada”, “Toyota”,1990, “male”) name address birth_date sex age “Taro Yamada” “Toyota” 1990 “male” 20 注:Time.now.year が2010を返すとすれば

演習1:クラスとインスタンス 注:補助資料を参照してください: 演習1.1.Itemクラス定義を用いて、以下の例を参考に、自分に当てはめて名簿項目(Itemインスタンス)を生成せよ(注意:女性の場合、性別は”female”) mydata = Item.new(“Taro Yamada”, “Toyota”, 1990, “male”) 演習1.2.上を実行後 mydata.age の値を表示させよ。 演習1.3. さらに mydata.age = 30 を実行させた後の mydata.birth_date と mydata.age の値を表示させよ。

クラス定義(追加):インスタンスメソッド そのインスタンスだけに適用される関数(メソッド)の定義: class Item   def initialize(n,a,b,s) @name = n ; @address = a @birth_date = b ; @sex = s @age = Time.now.year - b end attr_accessor :name, :address, :birth_date, :sex, :age def show(sep = “, ”) return “Name: “+@name+sep+” Sex: “+@sex+sep+”Age: “+@age 注:(sep=“,”) は、メソッド(関数)の引数が省略できること、また省略された場合に”,”が値となることを表すRubyの記法

演習2:クラスとインスタンス 注:補助資料を参照してください: 演習2(発展):  (1) 複素数を表すクラスを定義せよ。そのクラスの名前を Complex とし、パーツは二つ、 real (reと略す、実部) と imaginary (im と略す、虚部)。 (2) 補助資料の例にならって、複素数同士の引き算と割り算をするメソッドを付け加えよ。 (3) インスタンスを2つ以上つくり、計算がちゃんと行われることを確かめよ。

複素数について 2つの複素数を (a+bi), (c+di)とすると(a,b,c,dは実数, iは虚数) 足し算: (a+bi) + (c+di) = (a+c) + (b+d)i 引き算: (a+bi) - (c+di) = (a-c) + (b-d)i 掛け算: (a+bi) * (c+di) = (a*c - b*d)+(b*c + a*d)i 割り算: (a+bi) / (c+di) = (a*c + b*d)+(b*c - a*d)i c2 + d2 c2 + d2 参考: (a+bi) (a+bi) (c - di) (a*c + b*d) (b*c -a*d)i (c+di) (c+di) (c - di) c2 + d2 c2 + d2 (c –di)は(c+di)の共役複素数 * +

… (予習)リストの必要性とポインタ 名簿のような「表」を記憶することを考える   普通の方法: 1行分記憶するのに必要な記憶の大きさをkバイトとして、コンピュータ上に固定した記憶場所を確保して使う 1行k バイト k 2k …

リストの必要性とポインタ(続) 表方式の特徴:検索が容易 n件目のデータは、n*k~(n+1)*k-1の範囲に入っている 表方式の欠点:データの削除や挿入の手間が大きい   例:1番目のデータを削除したら、その後のデータをすべて一行ずつ前に移動しなければならない

リストの必要性とポインタ(続) リスト(線形リスト):表方式の欠点を解消 リスト(線形リスト)の基本単位:セル(Cell) データの挿入、削除の手間が軽減  ただし、記憶場所が多く必要、データの検索(アクセス)の手間がかかる、という欠点あり リスト(線形リスト)の基本単位:セル(Cell) data データ部 next ポインタ データ部: データの記憶用 ポインタ部:別なセルのアドレス

セル(Cell) 線形リスト構造を表現する基本単位セル  例えて言えば、連結器つきの車両  つながったセルの図