データおよび次データへのポインタの組を1つの単位として、幾つもの組を1列に継いで管理するデータ構造を、線型リスト(linear list)という。
リスト構造の先頭ノードheadは、管理に使うノードであり、データを格納しない。2個目のノード以降がデータを格納する。最終のノードは、次ノードへのポインタをNULLとする。
数の線型リストの例 ⇒ linearlist00.c
プログラム linearlist00.c の動作イメージを以下に示す。
赤い部分が、変化している部分である。
ポインタ型の変数に代入すると、同じ終点を指す矢印ができる。
前回の第4回では、画像ファイルの入出力は既存のオブジェクトファイルを使い、メイン関数は自作した。今回は、逆に、線型リストの操作のオブジェクトファイルを自作する。作成手順は次のとおりである。
list0501.c と linearlist.c を組み合わせると、linearlist00.c と同等の動作をする。組み合わせてコンパイルする方法は、第4回のコンパイルと同様、次のようにする。
以上をまとめる。
分割コンパイルでは、コンソール上での操作が多い。操作内容は、Makefile に定義し、make コマンドで起動する。
CC = gcc linearlist.o: linearlist.c linearlist.h $(CC) -c linearlist.c list0501.o: list0501.c linearlist.h $(CC) -c list0501.c list0501: list0501.o linearlist.o $(CC) -o list0501 list0501.o linearlist.o clean: $(RM) *.o core.* list0501 |
list0501.c のメイン関数には、リストの先頭に要素を追加する操作が含まれている。この操作を関数 void list_push(Node *, int); として作成し、linearlist.c および linearlist.h を拡充せよ。そして、list0501.cをベースにして簡略化したプログラムlist0502.cが動作するようにせよ。
線型リストに登録されたデータ(数値int)から、条件を満たすノードを検索する関数 Node *list_search_by_range(Node *, int, int) を作成せよ。条件とは、第2引数の数値以上、かつ、第3引数の数値以下、とする。返り値は、最初に検出したノード(ポインタ)とする。該当ノードが無い場合はNULLを返せ。また、ノードの値を表示する関数void list_print_node(Node *)を作成せよ。作成した関数は、linearlist.c および linearlist.h に登録せよ。メイン関数はlist0503.cとするので、動作を確認せよ。
10個の入力する数字のうち指定する範囲の値を全て表示するプログラムを作成せよ(prac0501.c)。ここで、入力された数字は全てリストに格納するものとする。そして、指定された範囲内の数値をリストから検索すること。ここで、課題1,2で作成した linearlist.c を活用すること。
/* prac0501.c */ /* 不足を補う */ main() { Node head, *p; int n, i, min, max; head.next = NULL; for( i = 0; i < 10; i ++ ){ printf("数を入力して下さい: "); scanf("%d", &n); list_push(&head, n); } printf("最小値を入力して下さい: "); scanf("%d", &min); printf("最大値を入力して下さい: "); scanf("%d", &max); /* 自分で作る */ } }
課題1から課題3で作成した linearlist.c および linearlist.h の最終プログラム、および課題3のプログラム(prac0501.c)にコメントを手書きして、提出せよ。
来週(5月26日)の授業開始時に集めます。
2005.5.17 by tokuhisa