質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

2回答

4358閲覧

Javaでのヒープソートのプログラムについて質問です

DAISUKE0549

総合スコア12

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

1クリップ

投稿2017/06/10 13:34

Java

11.public class HeapSort { 22. // 配列の要素a[i1]とa[i2]を交換 33. static void swap(int[] a, int i1, int i2) { 44. int t = a[i1]; 55. a[i1] = a[i2]; 66. a[i2] = t; 77. } 88. 99. // a[left]-a[right]をヒープ化 1010. static void downHeap(int[] a, int left, int right) { 1111. int temp = a[left]; // 根 1212. int child; // 大きいほうの子 1313. int parent; // 親 1414. 1515. for (parent = left; parent < (right + 1) / 2; parent = child) { 1616. int cl = parent * 2 + 1; // 左の子 1717. int cr = cl + 1; // 右の子 1818. if (cr <= right && a[cr] > a[cl]) { 1919. // cr <=rightの条件より右の子は存在しなくてもエラーにならない 2020. child = cr; 2121. } else { 2222. child = cl; 2323. } 2424. if (temp >= a[child]) { 2525. break; 2626. } 2727. a[parent] = a[child]; 2828. } 2929. a[parent] = temp; 3030. } 3131. 3232. // ヒープソート 3333. static void heapSort(int[] a) { 3434. int n = a.length; 3535. for (int i = (n - 1) / 2; i >= 0; i--) { // a[i]-a[n-1]をヒープ化 3636. downHeap(a, i, n - 1); 3737. } 3838. for (int i = n - 1; i > 0; i--) { 3939. swap(a, 0, i); // 最大要素と未ソート部末尾要素を交換 4040. downHeap(a, 0, i - 1); // a[0]-a[i - 1]をヒープ化 4141. } 4242. } 4343.}

こちらの本で書かれているヒープソートのプログラムについて質問です。
35行目のfor文のiの初期条件である(n - 1) / 2と
15行目のfor文の条件式ででてくる(right + 1) / 2が何を表しているのかが分かりません。
テキストによるとメソッドdownHeapは配列をヒープ化していくときに、最下流の右側から始めて左側へと進んでいき、そのレベルが終了したら一つ上流側へと移動しながら、部分木をヒープ化していくと書いてあります。
上記の2つのfor文の中の(n - 1) / 2と (right + 1 ) / 2によって配列の適切な位置からヒープ化を始められるというのはnに具体的な値を代入していくことで確認できたのですが、それぞれ2つの値が何を表していて、それらを(n - 1) / 2と (right + 1) / 2から求められるかが分からないので、教えて頂きたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

まず、おそらく34行目は

java

134. int n = a.length - 1;

の間違いです。

ヒープソートは下手に文章で説明するよりも図的に理解したほうがいいです。→ヒープソート

35行目のfor文のiの初期条件である(n - 1) / 2

これは配列最後の要素の親のインデックスに当たります。epistemeさんの言う通り、この番号以降の要素は子を持ちません。ここからさかのぼって順次ヒープ構造にしていくということになります。

15行目のfor文の条件式ででてくる(right + 1) / 2

これはヒープ構造にしようとしている範囲内で、子を持たない最初の要素のインデックスを意味します。ヒープ構造にする基準となる親がそこを超えたら、ヒープ構造化完了ということになります。

「なぜ出てくるか」に関して一応数学的な説明を加えることはできますが、参考リンクの図の番号(配列インデックスの番号)の法則性を眺めて理解できればそれで十分です。

投稿2017/06/10 14:52

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

DAISUKE0549

2017/06/11 02:22

回答ありがとうございました。 (n - 1) / 2と(right + 1) / 2が表しているものが理解することが出来ました。 ご指摘頂いたプログラミングのミスですが、おそらくは 34行目の int n = a.lengthは正しく 35行目を for (int i = (n - 1) / 2; i >= 0; i--)とするのではなく、 for(int i = (n - 2) / 2; i >= 0 ; i--)とするのが正しいのかと思います。 要素数nが偶数の場合 (n - 1) / 2は配列最後の要素の親のインデックスを表しますが、 nが奇数場合は子を持たない最初のインデックスを表していました。 「なぜ出てくるときは」もう少し自分で考えてみようと思います。 おそらくですが、配列の要素数nと2分木の段数kとした時に、2^(k-1) <= n <= 2^k - 1ということが関係しているのではないかと今のところ思っています。
guest

0

35行目のfor文のiの初期条件である(n - 1) / 2と 

15行目のfor文の条件式ででてくる(right + 1) / 2が何を表しているのかが分かりません。

(n-1)/2以降の要素は子を持たない(のでそこまで降りれば十分)ってことです。

投稿2017/06/10 13:46

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

DAISUKE0549

2017/06/11 01:52

回答ありがとうございました。(n-1)/2が表す意味を理解すことが出来ました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問