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 は適宜追加すること。)