キューについても復習がてら実装してみます。
キューのデータ構造を実装
キューのデータ構造は配列で実現し、リングバッファにします。
enqueueとdequeueの関数を実装しています。
バッファがフルか空かの判定は、enqueueとdequeue時に行い、
enumで定義した定数で状態管理をしています。ここが今回少し悩んだ箇所です。いくつか方法がありますが、最終的にわかり易さを優先して、フラグで状態管理することにしました。
下記が実装したソースコードになります。
main関数でdequeueとenqueueをしています。
$ cat queue.c
#include <stdio.h>
#define SIZE 3
enum status{
EMPTY,
AVAILABLE,
FULL
};
typedef struct{
int data[SIZE];
int head;
int tail;
int flag;
}queue_t;
//キューの中身をprint出力
void printQueue(queue_t* pQueue){
int i;
for(i = 0; i <= SIZE - 1; i++){
printf("%d ", pQueue->data[i]);
}
printf("\n");
}
//キューの初期化
void initQueue(queue_t* pQueue){
int i;
//キューの中身を0埋め
for(i = 0; i <= SIZE - 1; i++){
pQueue->data[i] = 0;
}
//初期化
pQueue->head = 0;
pQueue->tail = 0;
pQueue->flag = EMPTY;
printQueue(pQueue);
}
//enqueue関数
void enqueue(queue_t* pQueue, int value){
printf("enQ(%d)\n", value);
//キューがFullの処理
if(pQueue->flag == FULL){
printf("Full\n");
return;
}
//キューがFullでないので、enqueue操作
pQueue->data[pQueue->tail] = value;
//リングバッファのため、tailが配列の終端だったら0にする
if(pQueue->tail == SIZE - 1){
pQueue->tail = 0;
//終端でなければ、tailをインクリメント
}else{
pQueue->tail++;
}
//フラグの更新
if(pQueue->tail == pQueue->head){
pQueue->flag = FULL;
}else{
pQueue->flag = AVAILABLE;
}
printQueue(pQueue);
}
//dequeue関数
void dequeue(queue_t* pQueue){
printf("deQ\n");
//キューがEmptyの処理
if(pQueue->flag == EMPTY){
printf("Empty\n");
return;
}
//キューがEmptyでなければ、dequeue操作
pQueue->data[pQueue->head] = 0;
//リングバッファのため、headが配列の終端だったら0にする
if(pQueue->head == SIZE - 1){
pQueue->head = 0;
//終端でなければ、headをインクリメント
}else{
pQueue->head++;
}
//フラグの更新
if(pQueue->tail == pQueue->head){
pQueue->flag = EMPTY;
}else{
pQueue->flag = AVAILABLE;
}
printQueue(pQueue);
}
int main(){
queue_t queue;
queue_t* pQueue = &queue;
initQueue(pQueue);
dequeue(pQueue);
enqueue(pQueue, 1);
enqueue(pQueue, 2);
enqueue(pQueue, 3);
enqueue(pQueue, 4);
enqueue(pQueue, 5);
dequeue(pQueue);
dequeue(pQueue);
dequeue(pQueue);
dequeue(pQueue);
dequeue(pQueue);
enqueue(pQueue, 1);
enqueue(pQueue, 2);
enqueue(pQueue, 3);
enqueue(pQueue, 4);
dequeue(pQueue);
dequeue(pQueue);
dequeue(pQueue);
dequeue(pQueue);
enqueue(pQueue, 1);
dequeue(pQueue);
dequeue(pQueue);
enqueue(pQueue, 1);
enqueue(pQueue, 2);
enqueue(pQueue, 3);
dequeue(pQueue);
dequeue(pQueue);
dequeue(pQueue);
dequeue(pQueue);
dequeue(pQueue);
enqueue(pQueue, 1);
enqueue(pQueue, 2);
enqueue(pQueue, 3);
return 0;
}
下記が実行結果になります。EMPTYとFULLの状態遷移、またenqueueとdequeueの動きも確認できます。
enqueueとdequeueをそれぞれ交互に繰り返して、リングバッファのデータ構造となっていることも確認できます。
(配列の終端までenqueueされた後、配列の先頭からenqueueされています)
$ gcc queue.c -o queue $ ./queue 0 0 0 deQ Empty enQ(1) 1 0 0 enQ(2) 1 2 0 enQ(3) 1 2 3 enQ(4) Full enQ(5) Full deQ 0 2 3 deQ 0 0 3 deQ 0 0 0 deQ Empty deQ Empty enQ(1) 1 0 0 enQ(2) 1 2 0 enQ(3) 1 2 3 enQ(4) Full deQ 0 2 3 deQ 0 0 3 deQ 0 0 0 deQ Empty enQ(1) 1 0 0 deQ 0 0 0 deQ Empty enQ(1) 0 1 0 enQ(2) 0 1 2 enQ(3) 3 1 2 deQ 3 0 2 deQ 3 0 0 deQ 0 0 0 deQ Empty deQ Empty enQ(1) 0 1 0 enQ(2) 0 1 2 enQ(3) 3 1 2
動作確認も兼ねていたので、少々main関数が長くなってしまいましたね。。
