お茶の水女子大学 人間文化創成科学研究科 理学専攻 情報科学コース 2017年8月実施 情報基礎 問題1
Author
祭音Myyura (co-authored with GPT 5.6 SOL)
Description
以下は、char 型の文字の配列 table に入っている 個の文字 table[1] から table[n] を昇順に整列する C 言語で書かれたプログラムの一部である。関数 sort は内部で関数 insert を使っている。char 型の値の間には、アルファベット順に 'a' < 'b' < ... という大小関係が定義されている。また、各行の行頭に行番号を付してある。
1 void insert(char w, int j) {
2 if (j > 1 && w < table[j-1]) {
3 table[j] = table[j-1];
4 insert(w, j-1);
5 } else {
6 table[j] = w;
7 }
8 }
9 void sort(int i) {
10 if (i > 1) {
11 sort(i-1);
12 insert(table[i], i);
13 }
14 }
-
関数
insertおよびsortの動作の概要をそれぞれ説明せよ。 -
関数
sortを引数 で呼び出す、すなわちsort(1)を実行すると何が起こるか。 -
で、配列
tableの初期状態がtable[0]から順にi: 0 1 2 3 4 5 6 7
table[i]: ? s e r v i c eであったとする。ここで
table[0]の値は不定である。このときsort(7)を呼び出すと、その後 行目でsort自身が何度も再帰的に呼び出される。sortが呼び出されるたびに、その引数 の値を呼び出される順に書き下せ。sort(7)を 回目と数えると、最終的に何回sortは呼び出されるか。 -
(3) で求めた
sortの再帰呼出しのうち、最後の再帰呼出しであるsort(1)が終了すると、次に 行目でinsertが呼び出される。このときのinsertの引数 と の値は何か。 -
(4) で
insertが呼び出されるまではtableへの代入は行われていないので、この時点でのtableの状態は (3) に示したままである。(4) のinsertの呼出しを実行すると、 行目の代入文は何回実行されるか。 -
(4) の
insertの呼出しが終了した時点でのtableの内容を書き下せ。 -
同様に、その後 行目で
insertが呼び出されるたびに引数 と の値を順に書き下せ。さらに、各insertの呼出しが終了した時点でのtableの内容も書き下せ。ただし、 行目の再帰呼出し終了時は書き下さなくてよい。 -
(3) の
sort(7)の呼出しを行うと、結局、合計で 行目の代入文は何回実行されるか。 -
一般に、整列するデータ数が だったとき、 行目の代入文は最大で何回、最小で何回実行されるか。 を使って表せ。また、それぞれどのような場合か説明せよ。
-
このプログラムの計算量はいくらか。 を使って表せ。
-
関数
insertおよびsortの停止性をそれぞれ議論せよ。 -
番兵を使うことで、 行目の
if文の条件のうちj > 1を削除したい。どのように関数insertを変更すればよいか、具体的に示せ。 -
このプログラムが正しいこと、すなわち、整列するデータ数が だったとき
sort(n)の実行後は配列table[1]からtable[n]が昇順に並んでいることを示せ。
题目描述
给定一段以递归实现的插入排序程序:解释两个函数,追踪 service 的递归调用、参数、数组状态和移动次数;分析最好/最坏次数、复杂度与终止性;用哨兵改写边界判断,并证明程序正确。
Kai
(1)
insert(w,j) は、昇順に整列済みの table[1..j-1] に w を挿入する。w より大きい要素を一つずつ右へ移し、適切な位置に w を置く。
sort(i) はまず sort(i-1) で先頭 個を整列し、次に table[i] をそこへ挿入する。したがって再帰的な挿入ソートである。
(2)
i > 1 が偽なので何も行わず、直ちに終了する。
(3)
呼出しは
であり、合計 である。
(4)
sort(2) の第 行から呼ばれるので
(5)
e < s なので s を一度右へ移す。したがって第 行は 実行される。
(6)
終了時は
e s r v i c e
である。
(7)
第 行からの最上位の呼出しだけを順に示す。
呼出し終了時の table[1..7] | ||
|---|---|---|
r | 3 | e r s v i c e |
v | 4 | e r s v i c e |
i | 5 | e i r s v c e |
c | 6 | c e i r s v e |
e | 7 | c e e i r s v |
(8)
第 行の実行回数は入力列の転倒数に等しい。service の転倒数は
である。
(9)
最小値 は初めから昇順の場合、最大値 は全要素が相異なり降順の場合に達する。
(10)
最悪時間計算量は 、最良時間計算量は である。相異なる入力の順列が一様に与えられるとき、平均時間計算量も となる。再帰呼出しに使う補助領域は である。
(11)
insert が再帰するとき は必ず 減少し、 では条件が偽になるので停止する。sort でも再帰ごとに が 減少して に到達し、その後に呼ぶ有限個の insert も停止する。ゆえに両関数は停止する。
(12)
table[0] に挿入対象自身を番兵として置けばよい。
void insert(char w, int j) {
table[0] = w;
if (w < table[j - 1]) {
table[j] = table[j - 1];
insert(w, j - 1);
} else {
table[j] = w;
}
}
では w < table[0]、すなわち w < w が偽となるので、配列外へ進まない。
(13)
に関する帰納法で示す。 では明らかである。sort(i-1) の終了後に table[1..i-1] が昇順であると仮定する。
insert(table[i],i) は、挿入値 より大きい末尾要素だけを右へ移し、残った要素の直後に を置く。したがって要素の多重集合を変えずに table[1..i] を昇順にする。帰納法により sort(n) の終了後、table[1..n] は昇順である。