Presentation is loading. Please wait.

Presentation is loading. Please wait.

ヒープソート.

Similar presentations


Presentation on theme: "ヒープソート."— Presentation transcript:

1 ヒープソート

2 二進木とは 木はグラフの特殊なものである。 木とは「根」と呼ばれるただ一つの頂点(節点、ノードともいう)と
 それに接続する頂点、頂点と頂点をつなぐ枝(アークともいう)から  構成される 図示すると

3 2進木 根 枝で接続された2つの頂点のうち、上にあるものを「親」、下にあるものを「子」という
深さ0 深さ1 深さ2 枝で接続された2つの頂点のうち、上にあるものを「親」、下にあるものを「子」という 頂点の深さとは、根からその頂点までの枝の個数のこと 2進木: どの頂点もその子の個数は高々2個に限られる木 子は親頂点に対し「左の子」「右の子」と呼んで区別する

4 高さ 2 の二進木 (1) (2) (3) (5) (6) (4) (8) (9) (7) (10) (11) (12)

5 高さ 2 の二進木(続き) (13) (14) (15) (16) (18) (17) (21) (19) (20)

6 ここで考える「木」 頂点に「数値」が記憶されている 頂点を u で表すと、記憶された数値は f(u) で表す
頂点と頂点の間の枝、ある方法で指定される(後述)

7 { { 配列を用いた2進木の表現 { 図による二進木 … … 配列による表現 ① ② ③ ⑤ ⑥ ⑦ ④ ⑨ ⑧ 1 根 2 深さ1 3 4
1 根以外は 2 偶数: 左の子 深さ1 3 4 奇数: 右の子 深さ2 5 6 7 8 深さ3 9 図による二進木 配列による表現

8 ヒープ 親 子 ヒープ(heap)とは、特殊な二進木
定義 高さkの二進木Tがヒープであるための必要十分条件は次の (i), (ii)を満たすこと  (i) 深さ0 ~ k-1 の可能な頂点はすべて使われ、 深さkの頂点は左から順に使われている  (ii) 頂点uが頂点vの親なら    uの値( f(u) ) ≧ vの値( f(v) ) この条件は「配列」で2進木を表すと、わかりやすい

9 「可能な頂点」と「使われている」 「可能な頂点」は3個 (1) (2) 高さ 1 の二進木を考える ① 木の頂点になりうるもの ② ③ ①
実際に木の頂点になっている (1) (2) ①と②が使われ③は使われていない ①と③が使われ②は使われていない

10 { { 配列を用いたヒープの表現 { 二進木による表現 … … 配列による表現 ① ② ③ ⑤ ⑥ ⑦ ④ ⑨ ⑧
1 根以外は 2 偶数: 左の子 深さ1 3 4 奇数: 右の子 深さ2 5 6 ヒープの条件(i)は配列表現において、 1から順に要素が入っている、ということ 7 8 深さ3 9 二進木による表現 注目:深さkの一番左の子の番号は 2k 配列による表現 それでは一番右の子の番号は ?

11 ヒープの特徴 二進木 1 頂点の番号のつけ方: 上から下、左から右 3 2 6 7 4 5 9 8 10
この番号の付け方から、高さ n (> k)のヒープでは、 ★深さ k の最も左の頂点の番号は 2k ★深さ k の最も右の頂点の番号は 2(k+1) - 1

12 ヒープの演習 ヒープの条件(i)を持つ 高さ2、頂点数6の二進木 を書け 高さ3、頂点数 11 の二進木 を書け
高さ2、頂点数6の二進木  を書け    高さ3、頂点数 11 の二進木 を書け 定義 高さkの二進木Tにおいて (i) 深さ0 ~ k-1 の可能な頂点はすべて使われ、 深さkの頂点は左から順に使われている

13 ヒープの演習(続) 3. 右の配列に対応 する二進木を書け。 ただし、ヒープを配 列で表す規則に従 うとする。
 ただし、ヒープを配 列で表す規則に従 うとする。  これはヒープの条 件を満たしている か? 1 30 2 25 3 28 4 20 5 24 6 26 7 18 8 19 9 11 10 11

14 ヒープの演習(続) 4. 以下の二進木に対応する配列をかけ。ただし、ヒー プを配列で表す規則に従うとする。これはヒープの条 件をすべて満たすか? 20 10 15 4 7 11 6 1 5 2 3

15 ヒープへの要素の追加(挿入)手続き 手続き:以下の2ステップで行う 新たな要素を値とする頂点をヒープに追加 ⇒ 条件(i)を満たすところに
(2) 次に、ヒープ条件(ii)を満たすように修正する 定義 二進木Tにおいて (ii) 頂点uが頂点vの親なら    uの値≧ vの値

16 ヒープへの要素の追加(1) 8 5 7 3 10 例: に3を追加する… それには、ここしかない さらに、 10を追加する。。。
              に3を追加する… 定義 二進木Tにおいて (ii) 頂点uが頂点vの親なら    uの値≧ vの値 8 5 7 それには、ここしかない 3 そして、ヒープ条件(ii)を満たしているのでヒープが完成 10 さらに、 10を追加する。。。 これは、ヒープ条件(ii)を満たしていないので『修正』が必要

17 ヒープへの要素の追加(1)続き ヒープの条件(i)を満たすように要素を追加する ことは、
(b)二進木で表す場合、「可能な頂点を左から順に使う」 (a) 配列で表す場合は分かりやすい   ⇒ ヒープの最後の要素のインデックスを x とすれば、x+1 番目に要素を追加すれ     ばよい

18 ヒープへの要素の追加(2)「作り直し」 追加した頂点を v とする ヒープの条件(ii)は、 親頂点の値≧子頂点の値
    親頂点の値≧子頂点の値  だから、これが満たされていればOK.  そうでなければ、上の条件を満たすように、頂点を入れ替えていく (作り直しする)

19 ヒープへの要素の追加(2)続き ヒープへの要素の追加の完成 8 条件を破っている 5 7 条件を破っている 3 10

20 具体的に例を用いてヒープを作る 8 入力データ: { 8 5 7 3 10 5 7 9 6 1 20 } ヒープ条件(ii)を破っているので、『作り直し』が必要 3 10 9 6 1 20 問題: ヒープ条件(ii)が成り立つようにするには、どのように『作り直し』したらよいか?

21 ヒープソート(Heap Sort) ヒープを用いてソート(並び替え)を行う 手続き:
(1) x1, x2, …, xn からヒープ(木)を作る    計算量は O(n * log n)    ヒープ木においては根が最大の値の頂点 (2) 根と『最も深い頂点のうち最も右端の頂点』とを交換し、『根だった 頂点をヒープから切り離し』てからヒープを作り直す。この操作一回 ごとの計算量は O(log n) (3) (2)を繰り返し、切り離された頂点をすべて並べるとソート完成(新し く切り離された頂点が最小、古いものが最大)

22 ヒープソート(続き) 20 10 9 5 8 7 6 3 1 ≧ ≦ ヒープの作り直し(ヒープソートのステップ(2))
1. 根と『最も深く右側の頂点』とを交換し、根だった頂点を切り離す 20 2. ヒープ条件(ii)を満たすよう、ヒープを作り直す 10 9 親頂点と、子頂点のうち大きいほうを交換。 5 8 7 6 3 1 問題: ヒープをどのように作り直すか? 問題: この後ヒープをどのように作り直すか?

23 ヒープソートの真髄 ヒープを配列で表わす ⇒『木』よりも簡単なデータ構造で実行可能 インデックスによって、根の頂点を簡単に求めることができる
  ⇒『木』よりも簡単なデータ構造で実行可能 インデックスによって、根の頂点を簡単に求めることができる また、注目している頂点のインデックスから、その親や子の頂点が何か が簡単に計算できる 問題: 注目している頂点のインデックスをxとすると、その親と子の頂 点のインデックスは?

24 演習問題 配列を用いてヒープソートするプログラムを作る。 入力データからヒープ(配列で表現)を作る関数makeHeapを作れ
makeHeap(int a[], int h[], int n) : 配列a(n個の要素)からヒープの配列hを作る ヒープhのインデックス番号iとjの要素を交換する関数swapNodesを 書け: swapNodes(int h[], int i, int j) 最後の要素のインデックスを x とすると、 1~(x-1) までの要素を ヒープに作り直すコード(remakeHeap)を書け remakeHeap(int h[], int x)---配列hは、できていたヒープに対し、根 (h[1])と最後の要素h[x]を入れ替えた状態である。 (4) 以上を組み合わせて、ヒープソートを行う関数(heapSort)を書け   heapsort(int a[], int h[], int n) --- aが入力、要素数がn。h[1]~h[n]が ソートされた配列となるようにする: makeHeap, swapNodes, remakeHeapを使う


Download ppt "ヒープソート."

Similar presentations


Ads by Google