ヒープソート
Copyright(C) 1May2008 coskx TNCT
ソートのアルゴリズムのうち高速なアルゴリズムとして知られているヒープソートについて解説する
1.ヒープ | |
大きさ9の配列を考えよう。Fig.1のように値が保存されているものとする。
Fig.1 配列表現 |
この配列要素をFig.2のように配置し,線で結んだものを考える。
Fig.2 二分木表現 |
各要素を示している四角い箱のことを「ノード」という。各ノードは斜め下向きの2つの線で結んだ2つのノードを持つ。(下に配置されたノードでは,下位のノードを1つしか持たない場合もあり,まったく持たない場合もある。)
このように表現されたものを「二分木」と呼ぶ。
線で結ばれた3つのノードのグループのうち,上にあるノードを「親」,下にあるノードを「子」と呼ぶ。特に二分木の一番上のノードは「ルート(根)」と呼ばれる。ルートから順に図のように,要素に番号をつけると,それはノード番号となる。(Fig.2では0〜8)
Fig.3 親ノードと子ノード |
二分木の場合,ノード番号n の親は (n - 1) / 2,子は 2n + 1 と 2n + 2
である(整数型の割り算では,小数点以下は切り捨てられる)。
次のようなマクロ関数を用意しておくと便利である
便利なマクロ関数 |
#define LeftChild(n)
(2*(n)+1) |
図の二分木では,子同士の値の大小関係は決まっていないが,親と子の間では,親の値の方が子の値より大きくなっている(等しいこともある。)。このように,親子の間だけに値の大小関係がある木構造のことを,「半順序木(ヒープ)」と読んでいる。
2.ヒープソート | |
(1)ソートを求められたデータについて何らかの方法で半順序木(ヒープ)を構成する。
(2)0番要素(根)と最終要素を交換し,最終要素を木構造から切り離す。
(3)半順序木(ヒープ)が壊れたので(ルートのところだけが壊れている),再構築する。
(4)「(2)」へ戻り,「(2),(3)」を木構造がなくなるまで繰り返す。
ヒープソート実行の最初の様子をFig.4,Fig.5に示す。
Fig.4
ヒープソート(1) |
Fig.5
ヒープソート(2) |
プログラミングでは,最初の「半順序木(ヒープ)」構成作業と「半順序木(ヒープ)」再構成作業の2つの関数を作成するところが主な仕事となる。
3.半順序木(ヒープ)の構成 | |
「半順序木」になっていない配列の状態から開始し,0番要素から順に「半順序木」に登録する。
0番目要素は無条件に登録されますが,2番目以降の要素は,親要素と大きさ比較し,必要なら親要素と子要素を交換する。交換したら,親要素がルートでない限り,親要素はそのまた親要素と比較して,必要なら親要素と子要素を交換する。
List.1 ヒープ構成関数 x:ヒープを構成したい配列,num:配列の大きさ |
void heapify(int x[], int
num) |
4.半順序木(ヒープ)の再構成 | |
ルートの値のみ半順序木の定義を満たしていない状態(親のほうが小さい)を修正して,半順序木を作りたい。
ルートから始めて,その2つの子の大きい方と親とを比較して,親のほうが大きかったら交換する。
交換したら,子のそのまた子についても比較交換し,子がなくなるまで繰り返すことになる。
ヒープ再構成関数 x:ヒープを構成したい配列,num:配列の大きさ |
void shiftDown(int x[], int
num) |
5.ヒープソートプログラム例 | |
ヒープソートプログラム例 |
/*ノードの番号を次のようにつける */ #include "stdio.h" #define DEBUG #ifdef DEBUG void makedata(int x[], int
num) void printdata(int x[], int
num) #ifdef DEBUG2 /*小さい順ソート済みデータのチェック #define LeftChild(n)
(2*(n)+1) void heapify(int x[], int
num) void shiftDown(int x[], int
num) void HeapSort(int x[], int
num)
|
実行例の一部 |
41 67 34 0 69 24 78 58 62 64 5 45 81
27 61 91 95 42 27 36 =>91 81 78 67 64 69 61 62 58 41 5 24 45 27 34 0 36 42 27 95 =>81 67 78 62 64 69 61 36 58 41 5 24 45 27 34 0 27 42 91 95 =>78 67 69 62 64 45 61 36 58 41 5 24 42 27 34 0 27 81 91 95 =>69 67 61 62 64 45 34 36 58 41 5 24 42 27 27 0 78 81 91 95 =>67 64 61 62 41 45 34 36 58 0 5 24 42 27 27 69 78 81 91 95 =>64 62 61 58 41 45 34 36 27 0 5 24 42 27 67 69 78 81 91 95 =>62 58 61 36 41 45 34 27 27 0 5 24 42 64 67 69 78 81 91 95 =>61 58 45 36 41 42 34 27 27 0 5 24 62 64 67 69 78 81 91 95 =>58 41 45 36 24 42 34 27 27 0 5 61 62 64 67 69 78 81 91 95 =>45 41 42 36 24 5 34 27 27 0 58 61 62 64 67 69 78 81 91 95 =>42 41 34 36 24 5 0 27 27 45 58 61 62 64 67 69 78 81 91 95 =>41 36 34 27 24 5 0 27 42 45 58 61 62 64 67 69 78 81 91 95 =>36 27 34 27 24 5 0 41 42 45 58 61 62 64 67 69 78 81 91 95 =>34 27 5 27 24 0 36 41 42 45 58 61 62 64 67 69 78 81 91 95 =>27 27 5 0 24 34 36 41 42 45 58 61 62 64 67 69 78 81 91 95 =>27 24 5 0 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91 95 =>24 0 5 27 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91 95 => 5 0 24 27 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91 95 => 0 5 24 27 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91 95 0 5 24 27 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91 95 |