単連結リストの整列 #7 比較と交換の確認

隣接交換法での要素の比較と交換の様子を表示してみる。

test_node.c
...snip
#include <time.h>
...snip
static int index(node_t *first_node, node_t *node)
{
    int i = 0;
    node_t *p;
    for (p = first_node; p != NULL && p != node; p = p->next) i++;
    if (p == NULL) return 0;
    return i;
}

#ifndef DEBUG
#define DEBUG 0
#endif
#if DEBUG != 0
#define node_swap(p) \
    printf("swap %d and %d\n", index(first_node, p->next), index(first_node, p->next->next)), \
    node_swap(p), \
    node_print(first_node)
#endif

static void node_sort(node_t *first_node)
{
    node_t *p, *q;
    if (first_node == NULL || first_node->next == NULL || first_node->next->next == NULL) return;
    for (q = NULL; q != first_node->next->next; q = p->next) {
        for (p = first_node; p->next->next != q; p = p->next) {
            if (DEBUG) printf("compare %d and %d\n", index(first_node, p->next), index(first_node, p->next->next));
            if (p->next->val > p->next->next->val) node_swap(p);
        }
    }
}

#if DEBUG != 0
#undef node_swap
#endif

#ifndef N_DATA
#define N_DATA 9
#endif

int main(void)
{
    int i;
    node_t *first_node = node_new(0);
    srand(time(NULL));
    for (i = 0; i < N_DATA; i++) {
        node_append(first_node, (int)(rand() / (RAND_MAX + 1.0) * 900) + 100);
    }
    node_print(first_node);
    node_sort(first_node);
    node_print(first_node);
    return 0;
}

整列やリストに関わる関数のうち元のコードからの変更はnode_sort関数に一文加えるだけである。
さらに、表示のための補助用に新たに関数indexを定義している。
これは引数として渡した要素について、リストの先頭要素を1とする先頭要素からの序数を返す。
また、main関数で整列すべきデータを3桁の乱数にし、N_DATA個のデータを持つリストを作成する。

$ gcc -std=c89 -pedantic -Wall -Wextra -Werror -o test_node test_node.c -s -DN_DATA=5 -DDEBUG=1

$ ./test_node
711 938 807 302 893
compare 1 and 2
compare 2 and 3
swap 2 and 3
711 807 938 302 893
compare 3 and 4
swap 3 and 4
711 807 302 938 893
compare 4 and 5
swap 4 and 5
711 807 302 893 938
compare 1 and 2
compare 2 and 3
swap 2 and 3
711 302 807 893 938
compare 3 and 4
compare 1 and 2
swap 1 and 2
302 711 807 893 938
compare 2 and 3
compare 1 and 2
302 711 807 893 938

$ gcc -std=c89 -pedantic -Wall -Wextra -Werror -o test_node test_node.c -s -DN_DATA=0 -DDEBUG=1

$ ./test_node

$ gcc -std=c89 -pedantic -Wall -Wextra -Werror -o test_node test_node.c -s -DN_DATA=1 -DDEBUG=1

$ ./test_node
732
732

$ gcc -std=c89 -pedantic -Wall -Wextra -Werror -o test_node test_node.c -s -DN_DATA=2 -DDEBUG=1

$ ./test_node
738 669
compare 1 and 2
swap 1 and 2
669 738
669 738

$ gcc -std=c89 -pedantic -Wall -Wextra -Werror -o test_node test_node.c -s -DN_DATA=3 -DDEBUG=1

$ ./test_node
744 958 630
compare 1 and 2
compare 2 and 3
swap 2 and 3
744 630 958
compare 1 and 2
swap 1 and 2
630 744 958
630 744 958

$ gcc -std=c89 -pedantic -Wall -Wextra -Werror -o test_node test_node.c -s -DN_DATA=10

$ ./test_node
748 714 454 871 129 326 581 849 178 632
129 178 326 454 581 632 714 748 849 871

コンパイル時にDEBUGを非零に設定すると比較と交換のたびにその旨を表示し、
また、交換のたびにリストの状態を表示する。
リストに1個もデータが無い(N_DATA=0)ような場合も含めうまく動作しているようだ。