キューはスタックに比べて少しばかり,構造が複雑になっている.実際,それを直線的な イメージのメモリーにデータを追加しようとすると,以下のような問題が生じる.
教科書では,配列を用いたプリントキューのプログラム(p.123-125 List 4-5)を載せてい る.これも講義では説明しないので,各自,プログラムを解析せよ.
このプログラムでは,配列queue[]を使ってキューを実現している.配列 queue[]とキューの先頭を表す変数queue_firstと末尾を表す queue_lastはグローバル変数と宣言されているので,以下のキューを操作する関数 で直にアクセスすることができる.
キューを実装するための記憶領域が確保されたならば,それを操作しなくてはならない. キューの操作は2つで,データを追加することと,データを取り出すこと である.リスト2では,次の2つの関数でそれを行っている.
ここで使われているプログラムのテクニックは,すでに学習済みであるが,分かりにくい ものだけ述べておく.
2項演算子%は,割り算の結果の余りを返す.これをりようして,このプログラム では,queue_lastやqueue_firstの値を,
とサイクリック(cyclic:周期の)に変化させている.5の次の値を0にしているのである. これは,サイクリックに値を変化させて対時の常套手段である.
1 #define QUEUE_MAX 5+1 /* キューのサイズ+1 */ 2 #define QUEUE_EMPTY -1 3 4 /* 配列によるキュー構造 */ 5 int queue[QUEUE_MAX]; 6 /* キューの先頭位置(配列先頭からのオフセット) */ 7 int queue_first=0; 8 /* キューの末尾位置(配列先頭からのオフセット) */ 9 int queue_last=0; 10 11 /* キューにデータを追加する */ 12 void enqueue(int val) 13 { 14 /* lastの次がfirstならば */ 15 if((queue_last+1)%QUEUE_MAX ==queue_first) 16 { 17 /* 現在配列の中身は,すべてキューの要素で埋まっている */ 18 printf("ジョブが満杯です\n"); 19 } 20 else 21 { 22 /* キューに新しい値を入れる */ 23 queue[queue_last]=val; 24 /* queue_lastを1つ後ろにずらす。 25 もし,いちばん後ろの場合は,先頭にもってくる */ 26 queue_last=(queue_last+1)%QUEUE_MAX; 27 } 28 } 29 30 /* キューからデータを取り出す */ 31 int dequeue(void) 32 { 33 int ret; 34 35 if(queue_first==queue_last) 36 { 37 /* 現在キューは1つもない */ 38 return QUEUE_EMPTY; 39 } 40 else 41 { 42 /* いちばん先頭のキューを返す準備 */ 43 ret=queue[queue_first]; 44 /* キューの先頭を次に移動する */ 45 queue_first=(queue_first+1)%QUEUE_MAX; 46 return ret; 47 } 48 }
[転載について]
このペー
ジ中のリスト2のプログラムは,教科書として使用している以下の書籍
書名 | プログラミングの宝箱 アルゴリズムとデータ構造 ISBN4-7973-2419-8 |
著作者 | 紀平拓男・春日伸弥 |
出版社 | ソフトバンク パブリッシング株式会社 |