namazu-dev(ring)


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: namazu --sort=field:foobar



Satoru Takabayashi <satoru-t@xxxxxxxxxxxxxxxxxx> wrote:

># 現状では qsort(3) で文字列の並びを数値化して 
># nmz_mergesort() でソートし直すという変な操作を行なっていま
># す (手っ取り早く実装しようと思ったらこうなった)。この仕様
># は気持ちが悪いので、のちほど改善するつもりです。

改善しました。新しい実装では nmz_mergesort() を廃止して、ソー
トはすべて qsort(3) を使っています。(その方が速いでしょ?)

nmz_mergesort() で保証していた安定なソート (順序を保つ) を
qsort(3) で実現するために、 set_rank() なる関数を導入しまし
た。実に単純な仕掛けです。

安定なソートを実現する仕組み:

  1. ソートを行なう前に set_rank() 関数を呼び出して、現在の
     順序を記録する。これを ranking と呼ぶ。

  2. 比較部を 2重にする。もし、1回目の比較 (本来の比較)で 2
     つの要素が等価ならば、 ranking で再度、比較を行なう。

比較関数の例:

    int field_scmp(const void *p1, const void *p2)
    {
        hlist_data *v1, *v2;
        int r;
    
        v1 = (hlist_data *) p1;
        v2 = (hlist_data *) p2;
    
        r = strcmp(v2->field, v1->field);
        if (r == 0) {
            /* NOTE: comparison "a - b" is not safe for NEGATIVE numbers */
            r = v2->rank - v1->rank;
        }
        return r;
    }

この関数ではまず、

  r = strcmp(v2->field, v1->field);

でフィールドの情報 (Subject: や From: ) で比較を行ない (降順
のソートが標準なので v2, v1 の順)、それが等価ならば、

  r = v2->rank - v1->rank;

で ranking で再度、比較を行ないます。ranking は必ず、正数な
ので、単純に二つの数値を引き算しています。

これで、安定なソートが保証できます。(馬鹿馬鹿しいほど素朴な
方法ですが)

# いかがなものでしょ? > 古川さん

-- Satoru Takabayashi