プログラミング 4 木構造とヒープ.

Slides:



Advertisements
Similar presentations
区間グラフにおける区間表現からMPQ-treeを効率よく構成するアルゴリズム
Advertisements

4.3 マージソート.
離散システム特論 整列(sorting)アルゴリズム 2.
ヒープソートの演習 第13回.
2 分探索木 Binary Search Tree 実行可能な操作 計算量 木の高さは,最悪 O(n) n = |A| : 要素の個数
アルゴリズムとデータ構造 第8回 ソート(3).
第10回 整列 ~ バブルソート,挿入ソート,選択ソート~
第11回 整列 ~ シェルソート,クイックソート ~
アルゴリズムとデータ構造 2013年6月18日
アルゴリズムとデータ構造1 2005年7月8日
アルゴリズムとデータ構造 2010年7月5日
第11回 整列 ~ バケットソート,基数ソート,ヒープソート~
On the Enumeration of Colored Trees
Problem G : Entangled Tree
アルゴリズムとデータ構造 第6回演習解答 2015/11/18実施 アルゴリズムとデータ構造 2015.
アルゴリズムとデータ構造 2012年6月14日
データ構造とアルゴリズム 第7回 木 ~ データ構造(3)~.
探索アルゴリズム (1) 第7講: 平成21年11月13日 (金) 4限 E252教室.
コンピュータアルゴリズム2 6. コンテナの実現 田浦
ヒープソートの復習.
データ構造と アルゴリズム 第八回 知能情報学部 新田直也.
大岩 元 慶応大学環境情報学部 二分木 データ構造とプログラミング(10) 大岩 元 慶応大学環境情報学部
アルゴリズムとデータ構造 2011年6月14日
アルゴリズムとデータ構造 第7回探索のためのデータ構造(1) 2015/11/18 アルゴリズムとデータ構造 2015.
第11回 整列 ~ シェルソート,クイックソート ~
二分探索木によるサーチ.
算法数理工学 第3回 定兼 邦彦.
Cプログラミング演習 中間まとめ2.
アルゴリズムとデータ構造 2012年6月28日
アルゴリズムとデータ構造 2011年6月27日
アルゴリズムとデータ構造1 2005年7月26日
アルゴリズムとデータ構造1 2006年7月4日
アルゴリズムとデータ構造1 2006年6月16日
情報工学概論 (アルゴリズムとデータ構造)
二分木のメソッド(続き).
木の走査.
アルゴリズムとデータ構造勉強会 第6回 スレッド木
二分探索木における要素削除 データ構造とプログラミング(10)
アルゴリズムとデータ構造 第3章 ヒープ 6月10日分
第9回 優先度つき待ち行列,ヒープ,二分探索木
データ構造と アルゴリズム 第七回 知能情報学部 新田直也.
データ構造と アルゴリズム 第六回 知能情報学部 新田直也.
離散数学 07. 木 五島.
基本情報技術概論(第6回) 埼玉大学 理工学研究科 堀山 貴史
Cプログラミング演習 第10回 二分探索木.
プログラミング 4 整列アルゴリズム.
アルゴリズムとデータ構造 2010年7月26日
プログラミング 4 探索と計算量.
簡易データベース 情報画像工学実験 I : 実験2 担当:関屋大雄(工学部1号棟515室)
15.cons と種々のデータ構造.
アルゴリズムとデータ構造 第3章 ヒープ 5月31日分
アルゴリズムとデータ構造 第3章 ヒープ 5月31日分の復習
AVL木.
第9回 優先度つき待ち行列,ヒープ,二分探索木
アルゴリズムとデータ構造 2012年7月2日
アルゴリズムとデータ構造1 2008年7月24日
アルゴリズムとデータ構造 2011年6月28日
アルゴリズムとデータ構造 2011年6月16日
アルゴリズムとデータ構造 2013年7月1日
基本情報技術概論(第6回) 埼玉大学 理工学研究科 堀山 貴史
ヒープソートの復習 第12回.
情報工学概論 (アルゴリズムとデータ構造)
アルゴリズムとデータ構造1 2009年7月2日
アルゴリズムとデータ構造 2013年7月2日
平面走査法を使った 一般線分の 交点列挙アルゴリズム
ヒープソート.
ヒープソート.
アルゴリズムとデータ構造 2013年6月20日
参考:大きい要素の処理.
7.木構造 7-1.データ構造としての木 7-2.2分探索木 7-3.高度な木.
Presentation transcript:

プログラミング 4 木構造とヒープ

木構造 データを入れたノード (node;節点)とノード を結ぶリンク(link;枝) からなる ノードはリンクによって (複数の)子ノードを持 ち,木のような構造をし ている 木は「根」上にして書く 一番上のノードを根ノード 子のないノードを葉ノード

二分木 木構造は,1 つのノードが最大いくつの子ノードを持 てるかによって大別される 二分木,三分木,……,n 分木(3 以上は多分木という) この授業では特に重要な二分木(binary tree)を扱 う 以降,データとして整数を保持する二分木を扱う

二分探索木 二分木の中で,ノードの結び方に規則があるもののひ とつ 左の部分木には自分より小さい値,右の部分木には自 分より大きい値を持つノード 下の図では B < A < C A B C

二分探索木を作る 31,41,59,26,53,58,97,93 31 41

二分探索木を作る 31,41,59,26,53,58,97,93 31 41 59

二分探索木を作る 31,41,59,26,53,58,97,93 31 26 41 59

二分探索木を作る 31,41,59,26,53,58,97,93 31 26 41 59 53 58

二分探索木を作る 31,41,59,26,53,58,97,93 31 26 41 59 53 97 58 93

二分木の実現 ノードは構造体で作る struct node { int val; /* 値 */ struct node *left; /* 左子ノード */ struct node *right; /* 右子ノード */ }; 以降, typedef struct node Node; として話を進める 根ノードを指すポインタを root とする

二分探索木の探索(1) 大小関係を使って探索する(x を探索する) Node *search(int x) { Node *p = root; while (p != NULL) { if (p->val == x) return p; if (p->val > x) { p = p->left; } else { p = p->right; } } return NULL; }

二分探索木の探索(2) ノード数 n の二分探索 木の探索の計算量 木の高さは,二分探索木が うまく作られていれば O(log n) →探索の平均計算量は O(log n) 木がうまく作られていない 場合は木の高さは O(n) →探索の最悪計算量は O(n)

二分探索木の作成(1) 同じ値のノードの重複は許さないものとする 探索してノードを新しく作る場所が見つかったら生成 void addnode(int x) { Node *p, *q, *r; p = (Node *)malloc(sizeof(Node)); p->val = x; p->left = NULL; p->right = NULL; if (root == NULL) { root = p; } else { q = root; r = NULL; while (1) { r = q; if (x < r->val) { q = q->left; if (q == NULL) { r->left = p; return; } } else { q = q->right; if (q == NULL) { r->right = p; return; } } } } }

二分探索木の生成(2) ノード数 n の二分探索木の生成の計算量 うまく作れていれば木の高さは O(log n) →1 回のノードの追加の計算量は O(log n) これを n 回行うから,平均計算量は O(log n)×O(n) → O(n log n) うまく作れていなければ木の高さは O(n) →1 回のノードの追加の計算量は O(n) これを n 回行うから,最悪計算量は O(n)×O(n) → O(n2)

二分探索木をたどる 左の部分木→ノードを出力→右の部分木の順でたどれ ば昇順に出力できる void travtree(Node *p) { if (p == NULL) return; travtree(p->left); printf(“- %d ”, p->val); travtree(p->right); } 再帰呼び出しを使って記述する

二分木を解体する 左右の部分木を解体したあと,自身を解放する 順序に注意 void destroytree(Node *p) { if (p == NULL) return; destroytree(p->left); destroytree(p->right); free(p); return; }

その他の二分木の処理 ノードを数える 左の部分木のノード数+1+右の部分木のノード数 ノードを数える 左の部分木のノード数+1+右の部分木のノード数 高さを調べる 左の部分木と右の部分木の高さの高いほう+1 葉ノードを数える 右も左も子ノードがないノードの数を数える

ヒープ(1) 親ノードがつねに子ノードより大きく(小さく)なら ない二分木をヒープ(heap)という ヒープは配列で実装されることが多い ? 9 8 4 7 2 1 3 6 5 ? 9 8 4 7 3 2 1 6 5

ヒープ(2) ノード i について,親ノードは i/2,子ノードは i*2 および i*2+1 ? 9 8 4 7 3 2 1 6 5 9

ヒープを作る ヒープの配列を a[] とし,データ数を n とする 新しく x を追加するときは,x をいったん配列の末尾に入 れて,親ノードと比較して大きかったら入れ替える void insnode(int x) { int i, j, t; n++; a[n] = x; i = n; while (i > 1) { j = i / 2; if (a[i] < a[j]) return; t = a[i]; a[i] = a[j]; a[j] = t; i = j; } return; }

ヒープから取り出す 根ノードを取り出すと最大値(最小値)になる 末尾のノードを根ノードに移し,ヒープを再構成する int extnode(void) { int i, j, t; a[0] = a[1]; a[1] = a[n]; n--; i = 1; while (i * 2 <= n) { j = i * 2; if (a[j] <= a[j + 1]) j++; if (a[i] < a[j]) return a[0]; t = a[i]; a[i] = a[j]; a[j] = t; i = j; } return a[0]; }

ヒープソート ヒープに一度データを全部追加し,順に全部取り出せ ば整列ができる→ヒープソート(heap sort) ヒープの生成に O(n log n),ヒープからデータを取 り出すのに O(n log n) の計算量 → O(n log n)+O(n log n) → O(n log n)