このようにキューは非常に自然なメカニズムであるが、その実現はリストを 理解していれば簡単である。勿論、キュー自体は配列などを利用しても実現 出来るが、その場合には、どれが最初のデータで、どれが最後かを自分で 管理する必要があり、かえって面倒でさえある。しかし、場合によっては、 配列で実装しなければならない場合もあるので、リストでないと出来ない という訳では無いことを知っておく必要はある。ここでは、単純にリスト を使って実現する方法を考えよう。
まずデータが入ってくる場合であるが、入ってくるデータは全てリストの 最後に付け加える事にしよう。つまり、キューからデータを取り出す場合 には必ず、リストの先頭から取り出すようにする訳である。
まず、ヘッダーは次のようにする。
/* header of QUE */ typedef struct Que { struct Que *next; void *data; } QUE; static QUE *First; |
ここで typedef を用いて、QUE 型を作っているが、前の章での リストの実現方法と少し異なる点がある。それは、リストの最初の 要素の場所をどうやって保持するかという点であり、この例では 最初からモジュール内部に First という静的外部変数を用意して いる。静的外部変数であるために、モジュールの外から参照する ことはできない(15章を参照)が、モジュール内部ではグローバル な変数として扱える。このために、取り扱いは楽であるが、代わりに 複数のキューを持つことがこのままでは難しい。
キューに必要な関数はキューに追加する事と、キューから取り出す事 だけであるので実装はやさしい。
キューからデータを取り出す関数は最初の要素からデータを取り出し、 その要素をリストから取り除く。但し、もしキューにある要素がない 場合は NULL を返す。
void *get_que(void){ QUE *lp = First; void *data; if(lp==NULL){ /* データがキューにない */ return NULL; } data = lp->data; lp = lp->next; free(First); First=lp; return data; } |
次に、キューに一個新たにデータを追加する関数では、リストの最後にデータを 作って追加する、キューにデータがない場合にのみ、Firstを更新する。
void add_que(void *data){ QUE *lp=First; if(lp!=NULL){ while(lp->next!=NULL){ lp=lp->next; } lp = lp->next = (QUE*)malloc(sizeof(QUE)); }else{ lp = First=(QUE*)malloc(sizeof(QUE)); } lp->data = data; lp->next = NULL: return; } |