k番目に小さい数
クイックソートを使いk番目に小さい数を返す(平成27年 春 午後問8)
問題のイメージがどうしてもトレースできないので、プログラムを打ってみました。(c言語です)
添え字がゼロから始まるので、x[0]に捨てデータを入れて、個数nを計算するときに、そのデータ分を 1 引いてあります。
ル-プの途中で break があるのは伏兵
この問題の様に、ループの最後まで行ってループを抜けないで、途中で中途半端に break がある(出題時の行数は、16-17行)のは、どうも好きにはなれません。
下まで行って終わりかと思ったら、そうではなくて、途中までまたちょっと帰ってから、いくらかの処理をさせるのでした。
「構造化言語」と言われだした頃にプログラムを始めたので、breakを使う習慣など全くないもんだから、こんなのはめちゃくちゃ気持ちが悪い。
ル-プのカウントを制御してないのも嫌
それともう一つ、ル-プのカウントで制御してない(出題時の行数は、10、13行)のも嫌らしいですね。問題の引っ掛けになっているので、わざとそうしているのでしょうが、そんなことをするから、分からなくなる。添え字の範囲を超えないような制御は、少々野暮ったくても、しておくべきでしょう。
こんなん、間違いのもと。試験になんか出すな!
#include <stdio.h> int main(){ int x[] = {0,3,5,6,4,7,2,1}; /* 最初の 0 はダミー 添え字が[1]から始まるため */ int k = 3; /* 取り出すk番目の数 */ int i, j,m, n,Top,Last,Pivot,work; n = sizeof x / sizeof x[0] -1; /* データの個数 n */ printf("データ数 n = %d \n", n); for (m = 1; m <= n; m++) { printf("x[%d] = %d \n",m, x[m]); /* m カウント変数 */ } Top = 1; Last = n; while (Top < Last) { Pivot = x[k]; printf("\n 大ループ Pivot = %d \n", Pivot); /* Pivot設定 */ i = Top; j = Last; while (1) { while (x[i] < Pivot) { ++i; printf("i = %d \n", i); /* i Pivotより小さい数の位置 */ } while (Pivot < x[j]) { --j; printf("j = %d \n", j); /* j Pivotより大きい数の位置 */ } if (i >= j) { break; /* ループから抜ける */ } work = x[i]; x[i] = x[j]; x[j] = work; printf("\n入れ替えた x[%d] = %d と x[%d] = %d\n",i, x[i],j, x[j]); /* 大小の入れ替え */ ++i; --j; for (m = 1; m <= n; m++) { printf("x[%d] = %d \n", m, x[m]); /* m カウント変数 */ } } if (i <= k) { Top = j + 1; printf("i(%d)<= k(%d),j(%d) Top位置設定 = %d Last位置 = %d \n",i,k,j, Top, Last); /* Topの位置設定 */ } if (k <= j) { Last = i - 1; printf("i(%d), k(%d) <= j(%d) Top位置 = %d Last位置設定 = %d \n",i,k,j, Top, Last); /* Topの位置設定 */ } } printf(" \n\n "); printf(" n番目の数 = %d \n\n ", x[k]); for (m = 1; m <= n; m++) { printf("x[%d] = %d \n ", m, x[m]); /* m カウント変数 */ } return 0; }
実行結果
データ数 n = 7 x[1] = 3 x[2] = 5 x[3] = 6 x[4] = 4 x[5] = 7 x[6] = 2 x[7] = 1 大ループ Pivot = 6 i = 2 i = 3 入れ替えた x[3] = 1 と x[7] = 6 x[1] = 3 x[2] = 5 x[3] = 1 x[4] = 4 x[5] = 7 x[6] = 2 x[7] = 6 i = 5 入れ替えた x[5] = 2 と x[6] = 7 x[1] = 3 x[2] = 5 x[3] = 1 x[4] = 4 x[5] = 2 x[6] = 7 x[7] = 6 i(6), k(3) <= j(5) Top位置 = 1 Last位置設定 = 5 大ループ Pivot = 1 j = 4 j = 3 入れ替えた x[1] = 1 と x[3] = 3 x[1] = 1 x[2] = 5 x[3] = 3 x[4] = 4 x[5] = 2 x[6] = 7 x[7] = 6 j = 1 i(2)<= k(3),j(1) Top位置設定 = 2 Last位置 = 5 大ループ Pivot = 3 入れ替えた x[2] = 2 と x[5] = 5 x[1] = 1 x[2] = 2 x[3] = 3 x[4] = 4 x[5] = 5 x[6] = 7 x[7] = 6 j = 3 i(3)<= k(3),j(3) Top位置設定 = 4 Last位置 = 5 i(3), k(3) <= j(3) Top位置 = 4 Last位置設定 = 2 n番目の数 = 3 x[1] = 1 x[2] = 2 x[3] = 3 x[4] = 4 x[5] = 5 x[6] = 7 x[7] = 6