プログラミング言語 C

・ 次の関数は 整数配列を整列させるためのシェルソートである。

・ 1959年に D.L.Shell によって考えられた このソートアルゴリズムの基本概念は、

初期の段階で、単純な交換配列のような となりあった要素間の比較を行うのではなく、まず 遠くの離れた要素間の比較を行う

ことにある。

・ これは 大量の (データの) 無秩序を すばやく整列させるという利点をもち、したがって (ソートの) 後半では あまり多量の仕事を必要としない。

・ (なぜなら) 比較する要素間の間隔が しだいに小さくなり、それが 1 になると この整列法は事実上、(単純な) 隣接交換法となる (からである)。

  1. void shell_sort(int v[], int n)
  2. }
  3. int gap, i, j, tmp;
  4. for (gap = n/2; gap > 0; gap /= 2) {
  5. for (i = gap; i < n; i++) {
  6. for (j = i - gap; j >= 0 && v[j] > v[j+gap]; j -= gap) {
  7. tmp = v[j];
  8. v[j] = v[j+gap];
  9. v[j + gap] = tmp;
  10. }
  11. }
  12. }
  13. }

・ ここには 3つの入れ子になったループがある。

・ もっとも外側のループでは 比較される要素間の gap を その値が 0 になるまで n/2 から 2 で割りながら 小さくしていくよう制御している。

・ 真ん中のループでは 要素にそって進行している。

・ もっとも内側のループでは gap分だけ離れた 2つずつの要素を比較して 整列していない要素を (tmp を使って) 入れかえている。

・ gap は (その間隔を) 1 になるまで減らしていくので 最終的には 正しい整列になる。

・ for文の一般性(?)により、もっとも外側のループでは 順序だてて進行していないにもかかわらず、他のループと同一の形式をとっていることに注意してほしい。

・ C の演算子の 1つに コンマがある。この演算子は for文の中で もっともよく使われる。

・ コンマで分けられた 2つの式は 左から右へと計算され、右側の式の型と値が (そのまま この 2つの式全体の) 型と値になる

・ このように 多くの式を for文中の 各部分に記述することができ、インデックス中の並列処理が可能になる。

・ (当然のことだが) 関数引数や宣言中の変数を分離するときのコンマは 演算子ではないので、左から右へ 順に評価されるということは (C では) 保証されていない。

・ このコンマ演算子は (できれば) ひかえめに使うべきである。そのもっとも適切な使用法としては 相互に強く関連づけられた構文や 多段階にわたる計算を 1つの式に含めなければならない場合の マクロ がある。

・ 例として 文字列 s を その位置で逆順にする 関数 reverse() を示してみよう。

  1. include
  2. void reverse(char s[])
  3. {
  4. int c, i, j;
  5. for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
  6. c = s[i];
  7. s[i] = s[j];
  8. s[j] = c;
  9. }
  10. }
  11. /* strlen() は 文字列の長さを数える関数だった . . .よね ? */

・ 関数 reverse() の場合、要素の変換は 1つの (まとまった) 操作と考えることができるので コンマ演算子を 上のように使うのは 適切だと思われる。(p75-76)