2つのリストを単純に結合する操作、つまり、1つめのリストの後に、2つめのリストの先頭を繋げる操作を、append という。
append 操作のアルゴリズムは以下のようになる。
/* リスト l1 にリスト l2 を結合する */
void list_append(Node *l1, Node *l2) {
Node *p;
p = l1;
p の次ノードへのリンクが NULL でない間、以下を実行する。
p = p -> next;
p の次ノードへのリンクを l2 の最初のノードとする。
}
ここで、l2 の最初のノードとは、線型リストの最初に置かれたダミーノードではないことに、注意せよ。
例えば、l1 = [1,3,5,7] に l2 = [2,4,6,8] を append すると、l1 = [1,3,5,7,2,4,6,8] となる。
ソートされている2つのリストを合成し、ソートされた1つのリストとする操作を merge という。
merge 操作のアルゴリズムは以下のようになる。
/* リスト l1 にリスト l2 を順序(昇順)を保ち混ぜ合わせる(l2は破壊される) */
void list_merge(Node *l1, Node *l2) {
Node *p, *q, *t;
p = l1;
q = l2;
p の次ノードへのリンクが NULL でない間、以下を実行する。
もし、q の次ノードへのリンクが NULL であるならば、
return;
もし、p の次ノードの値より q の次ノードの値が小さいならば、
t に q の次ノードへのリンクを退避(代入)する。
q の次ノードへのリンクを t の次ノードとする。
t の次ノードへのリンクを p の次ノードとする。
p の次ノードへのリンクを t とする。
p を t とする。
そうでなければ、
p を p の次ノードとする。
p の次ノードを q の次ノードとする。
q の次ノードへのリンクを NULL とする。
}
例えば、l1 = [1,3,5,7] に l2 = [2,4,6,8] を merge すると、l1 = [1,2,3,4,5,6,7,8] となる。
以下の2つを両方とも取り組むこと。
main() {
Node root1, root2, root3;
root1.next = NULL;
root2.next = NULL;
root3.next = NULL;
list_push(&root1,1);
list_push(&root1,3);
list_push(&root1,5);
list_insert(&root2,4);
list_insert(&root2,9);
list_insert(&root2,2);
list_append(&root1,&root2);
list_insert(&root3,7);
list_insert(&root3,3);
list_insert(&root3,1);
list_merge(&root3,&root2); /* ← ここの関数内での過程を示すこと */
list_print(&root1);
printf("\n");
list_print(&root2);
printf("\n");
list_print(&root3);
}
プログラム作成に必要な、ライブラリ(numlist.c、numlist.h)、Makefile、および、mainのソースは次のものを利用すること。(「リンク先を保存」などブラウザのセーブ機能を使い、ダウンロードすること。Makefile は適宜追加すること。)