情報処理Ⅱ 第9回 2004年12月7日(火).

Slides:



Advertisements
Similar presentations
情報処理Ⅱ 第8回 2004 年 11 月 30 日(火). 2 本日学ぶこと 関数と変数 目的  関数を自分で定義し,変数の利用方法・範囲を明示的に制 限することで,適切な機能分割(モジュール化,再利用) を図る. してはいけないこと  main 関数のみで 100 行以上のプログラム  グローバル変数を駆使するプログラム.
Advertisements

情報処理Ⅱ 第7回:2003年12月2日(火). 問題(授業がつまらない人のため に) ぷよ連結問題 前提 : フィールドを2次元 配列で定義し,各マスの 「ぷよ」を int 型の値で表現 する. ある地点を入力に取り,そ れと連結する「ぷよ」の個 数を求めよ. 消去できる「ぷよ」 (N 個以上 連結するぷよと,それに隣接する特.
【事例演習5】  字句解析     解 説  “ハッシュを用いた字句解析の方法”.
情報処理Ⅱ 2006年12月8日(金).
ヒープソートの演習 第13回.
第11回 整列 ~ シェルソート,クイックソート ~
第11回 整列 ~ バケットソート,基数ソート,ヒープソート~
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
情報処理Ⅱ 2007年12月17日(月).
プログラミング論 I 関数の再帰呼び出し
第10回 ソート(1):単純なソートアルゴリズム
情報処理Ⅱ 2005年12月9日(金).
情報処理Ⅱ 2005年12月22日(木).
第8回 プログラミングⅡ 第8回
データ構造とアルゴリズム 分割統治 ~ マージソート~.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
第11回 整列 ~ シェルソート,クイックソート ~
プログラミング基礎a 第8回 プログラムの設計 アルゴリズムとデータ構造
アルゴリズムとデータ構造 2012年6月28日
アルゴリズムとデータ構造 2011年6月27日
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
第10回関数 Ⅱ (ローカル変数とスコープ).
アルゴリズムとデータ構造1 2006年6月16日
情報処理Ⅱ 2007年12月3日(月) その2.
プログラミング2 関数の再帰呼び出し
プログラミング入門2 第11回 情報工学科 篠埜 功.
講義では、Cプログラミングの基本を学び 演習では、やや実践的なプログラミングを通して学ぶ
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
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.
第5回放送授業.
プログラミング基礎a 第8回 プログラムの設計 アルゴリズムとデータ構造
プログラミング 4 整列アルゴリズム.
情報処理Ⅱ 第14回 2006年1月23日(月).
アルゴリズムとデータ構造 2010年7月26日
情報処理Ⅱ 第2回:2003年10月14日(火).
プログラミング 4 探索と計算量.
再帰的手続き.
プログラミング 4 木構造とヒープ.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
アルゴリズムとプログラミング (Algorithms and Programming)
文字列へのポインタの配列 static char *lines[MAXLINES]; lines[0] NULL
アルゴリズムとプログラミング (Algorithms and Programming)
アルゴリズムとデータ構造1 2008年7月24日
アルゴリズムとデータ構造 2013年7月1日
第5回 プログラミングⅡ 第5回
情報処理Ⅱ 2006年12月22日(金).
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
情報処理Ⅱ 2006年11月24日(金).
情報処理Ⅱ 第7回 2004年11月16日(火).
ヒープソート.
情報処理Ⅱ 2007年12月3日(月) その1.
プログラミング2 関数の再帰呼び出し
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
関数と再帰 教科書13章 電子1(木曜クラス) 2005/06/22(Thu.).
プログラミング演習I 2003年6月11日(第9回) 木村巌.
情報処理Ⅱ 第2回 2004年10月12日(火).
情報処理Ⅱ 2005年11月25日(金).
第10回 関数と再帰.
Q q 情報セキュリティ 第7回:2005年5月27日(金) q q.
オブジェクト指向言語論 第三回 知能情報学部 新田直也.
プログラミング入門2 第5回 配列 変数宣言、初期化について
情報処理Ⅱ 小テスト 2005年2月1日(火).
計算技術研究会 第5回 C言語勉強会 関数(function)を使う
情報処理Ⅱ 第3回 2004年10月19日(火).
情報処理Ⅱ 第8回:2003年12月9日(火).
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
計算機プログラミングI 第5回 2002年11月7日(木) 配列: 沢山のデータをまとめたデータ どんなものか どうやって使うのか
Presentation transcript:

情報処理Ⅱ 第9回 2004年12月7日(火)

暗号化問題 仕様 入力文にあるすべての'A'をα,すべての'B'をβ,…に置き換えて出力する.(単一換字暗号という.) 文字は,char型の任意の値とする.ただし'\0'を除く('\0'は必ず'\0'に置き換える,と考えてもよい). どの文字をどの文字に置き換えるかは,プログラムの中で指定する. 簡単な操作で,復号できるようにする.  Wagahai Ha Nekodearu  Zdjdkdl Kd Qhnrghdux 暗号化 復号

暗号化問題 方針 encrypt_ table … 'D' 'E' 'F' 'G' … +0 +'A' +'C' +1 +'B' +'D' 暗号化のための変換テーブルを,配列で保持する. char encrypt_table[256]; encrypt_table['A']の値 encrypt_ table … 'D' 'E' 'F' 'G' … +0 +'A' +'C' +1 +'B' +'D' +255

暗号化問題 方針(続き) 暗号化は,写像を用いる. a = 'A'; のとき,b = encrypt_table[a]; でbの値が'D'となるようにするには,あらかじめencrypt_table['A']の値を'D'としておけばよい. 復号のためのテーブルは,逆写像を用いて求める. char decrypt_table[256]; decrypt_table[encrypt_table['A']] = 'A'; gがfの逆写像 であるとは, g(f(x))=x

暗号化問題 方針(続き) 定義する関数 文字列形式の変換テーブルを,配列に変換する. 復号のためのテーブルの値を設定する. fが恒等写像 であるとは, f(x)=x 方針(続き) 定義する関数 文字列形式の変換テーブルを,配列に変換する. 復号のためのテーブルの値を設定する. 変換テーブルを恒等写像にする(変換のリセット). 変換テーブルを用いて,文字列を暗号化もしくは復号する. 暗号化と復号はどう区別する? ./encrypt Wakagai Ha Nekodearu ./encrypt -d Zdjdkdl Kd Qhnrghdux 「コマンドラインオプション」と呼ばれる

定義する関数(1) void reset_table(char *table) encrypt_ table ? 1 'A' 'B' … 変換テーブルを恒等写像にする(変換のリセット). encrypt_ table ? 1 'A' 'B' … 'C' 255 ? … ? ? ? … ? table +0 +'A' +'C' +1 +'B' +255 関数内の ローカル変数 (関数が終了すると,破棄される)

定義する関数(2) void set_encrypt_table(char *table, const char *from, const char *to) 文字列形式の変換テーブルを,配列に変換する. encrypt_ table … 'D' +'A' 'E' +'B' 'F' +'C' … table from to 'A' 'B' 'C' … '\0' 'D' 'E' 'F' … '\0'

定義する関数(3) void set_decrypt_table(char *table, const char *encrypt_table) 復号のためのテーブルを設定する(逆写像を作る). decrypt_ table … 'A' … table +0 +'A' +'C' +1 +'B' +'D' +255 encrypt_ table … 'D' … encrypt_ table +0 +'A' +'C' +1 +'B' +'D' +255

定義する関数(4) char *encrypt(const char *text, const char *table) 変換テーブルを用いて,文字列を変換する. 「暗号化」と「復号」の処理を共通化している! 戻り値は,変換された文字列で,static変数result(のポインタ値)となる. text 'W' 'a' 'g' 'a' 'h' 'a' 'i' '\0' table … 'D' 'E' 'F' 'G' … result 'Z' 'd' 'j' 'd' 'k' 'd' 'l' '\0' static領域(関数が終了しても,破棄されない) 戻り値

暗号化プログラムの補足 関数set_encrypt_tableの仮引数from, toはconst char *型である.このとき fromの参照先(const char型の値)を変更しようとしている. 暗号化のように,関数開始時点で長さがわからない文字列を入力にとり,それと同じ長さの暗号文を返すときは,生成する暗号文が配列領域をはみ出さないように配慮する. encrypt.cでは,100文字(ナル文字を加えて101バイト)を越える入力は,そこから無視している.

まとめ 関数を自分で定義することができる.関数を呼び出すとき,引数は値渡しで授受される. 変数には,型とは別の属性として,記憶域クラスと型修飾子を指定できる.static変数とauto変数とでは,大きく挙動が異なる. 「変数の定義」と「オブジェクトの生成」は別. オブジェクトの生成・破棄のタイミングに注意する.

次に学ぶこと 再帰(recursion) 用途 注意点 再帰的(帰納的,循環的)な定義 バックトラック(backtrack) 分割統治法(divide-and-conquer) 注意点 無限ループにならないようにする. 再帰を使わないほうがよいこともある.

再帰呼び出しとは 関数の内部で自分自身を呼び出すことを,再帰呼び出し(recursive call)という. 例:カウントダウンするプログラム 自作関数countdownの定義の中で,countdownを呼び出している.

なぜ再帰呼び出しが可能なのか? 同一の変数名x に対して複数の このようなデータ 構造を,「スタック」 オブジェクトが という. 生成される. このようなデータ 構造を,「スタック」 という. countdown x = 0 countdown x = 1 countdownの再帰呼び出しを終えたときの戻り先 countdownの呼び出し(関数処理)を終えたときの戻り先 countdown関数処理時に 生成されるオブジェクト main x = 2 main関数処理時に 生成されるオブジェクト num = 2

再帰呼び出しの注意点 出力の位置を変えると,カウントアップになる. カウントアップ,カウントダウンともに,再帰呼び出しなしの プログラムのほうが,効率はよい. なぜ再帰呼び出しは効率が悪いか? …関数呼び出しのコスト(オーバーヘッド)があるから.

再帰的な定義の例 階乗 フィボナッチ数列 再帰呼び出しを用いれば,シンプルに書ける. しかしこれらも,whileループのほうが効率がよい. 0! = 1, 1! = 1 n! = n×(n-1)! (n≧2) フィボナッチ数列 a1 = 1, a2 = 1 an= an-1 + an-2  (n≧3) 再帰呼び出しを用いれば,シンプルに書ける. しかしこれらも,whileループのほうが効率がよい.

分割統治法 対象領域を細分化して求め(分割),全体として正しい解になる(統治)ようにする. 例: クイックソート 4 7 3 8 6 1 2 5 2 8 5 7 6 1 3 4 「4より小」と 「4より大」に 分ける. 1 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8

ソート(sort) データを,何らかの基準で順番に並べること.「整列」ともいう. 例 試験の点数順に学生番号を出力する 時系列で出力される情報を,キーワードごとに並べる ソートの対象と なる個々の情報を 「レコード」という 学生番号:0003 氏名:さしすせそ 情処Ⅰの点数:90 情処Ⅱの点数:0 修得単位数: 24 学生番号:0002 氏名:かきくけこ 情処Ⅰの点数:60 情処Ⅱの点数:99 修得単位数: 48 学生番号:0002 氏名:かきくけこ 情処Ⅰの点数:60 情処Ⅱの点数:99 修得単位数: 48 学生番号:0001 氏名:あいうえお 情処Ⅰの点数:80 情処Ⅱの点数:75 修得単位数: 52 学生番号:0001 氏名:あいうえお 情処Ⅰの点数:80 情処Ⅱの点数:75 修得単位数: 52 学生番号:0003 氏名:さしすせそ 情処Ⅰの点数:90 情処Ⅱの点数:0 修得単位数: 24 学生番号で昇順ソート 情処Ⅰの点数で降順ソート (ソートの)「キー」という

ソートをする際の問題点 計算の手間 重複キー 処理時間(比較回数)が,レコード数の2乗に比例する方法は,遅い. レコード数nに対して,n log n に比例するだけの比較回数でソートできる方法が最善である. 重複キー キーが同じでもレコードが異なっていれば,別物として扱わなければならない. 安定性

文字列並べ替え問題 仕様 コマンドライン引数の各語を,昇順にソートして出力する. Mukashi Mukashi Aru Tokoroni Ojiisanto Obaasanga Sunde Imashita Aru Imashita Mukashi Mukashi Obaasanga Ojiisanto Sunde Tokoroni キーは,語の先頭文字とする. "Mukashi" > "Aru" "Aru" < "Tokoroni" "Ojiisanto" == "Obaasanga" クイックソートを用いる. 一般には(辞書順), "Ojiisanto" > "Obaasanga"

クイックソートの考え方 緑矢印から橙矢印までをソートしたい. 4 7 3 8 6 1 2 5 4≦7なので,何もせず 青矢印を進める. 4 7 3 8 6 1 2 5 4>3なので, 赤矢印を進めてから交換し,青矢印を進める. 4 3 7 8 6 1 2 5 4>1なので, 交換が発生する. 4 3 7 8 6 1 2 5 4 3 1 8 6 7 2 5

クイックソートの考え方 4 3 1 8 6 7 2 5 p = 基準値 <p≦ 未調査 p = 走査の位置 <p≦ 基準値未満 整数値またはポインタ値

クイックソートの考え方 4 3 1 8 6 7 2 5 4>2なので, 交換が発生する. 4 3 1 2 6 7 8 5 配列の走査は終了. 緑矢印と赤矢印の値を交換しておく. 2 3 1 4 6 7 8 5 赤矢印の左と右で別々にソートする.ここで再帰呼び出しを使用する. 2 3 1 4 6 7 8 5 1 2 3 4 5 6 7 8

まとめ 再帰呼び出しを用いて関数を定義すると,プログラムがすっきり書けることがある. 一般に,再帰を用いないほうが効率的である. 再帰的に定義された問題に適用すると,効果的. 一般に,再帰を用いないほうが効率的である. 関数内のauto変数は,関数呼び出しごとに生成される点に注意.