このようにキューは非常に自然なメカニズムであるが、その実現はリストを 理解していれば簡単である。勿論、キュー自体は配列などを利用しても実現 出来るが、その場合には、どれが最初のデータで、どれが最後かを自分で 管理する必要があり、かえって面倒でさえある。しかし、場合によっては、 配列で実装しなければならない場合もあるので、リストでないと出来ない という訳では無いことを知っておく必要はある。ここでは、単純にリスト を使って実現する方法を考えよう。
まずデータが入ってくる場合であるが、入ってくるデータは全てリストの 最後に付け加える事にしよう。つまり、キューからデータを取り出す場合 には必ず、リストの先頭から取り出すようにする訳である。
まず、ヘッダーは次のようにする。
/* 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;
}
|