循環キューを実装するC++プログラム
キューは、要素の集合を格納する抽象データ構造の一つです。キューはFIFO(First In First Out:先入れ先出し)方式を採用しており、最初に挿入された要素が最初に取り出されます。
循環キュー(Circular Queue)はキューの一種で、配列の末尾と先頭をつなげて円形にした構造を持っています。これにより、配列の後方に空きがなくても、先頭側の空きスペースを再利用できるという利点があります。
この記事では、挿入・削除・表示の3つの操作を実装した、循環キューのC++プログラムを紹介します。
循環キューの基本的な仕組み
循環キューでは、front(先頭)とrear(末尾)の2つのインデックスを使用して要素を管理します。
- 挿入(enqueue):rearを1つ進めてその位置に要素を格納します。rearが配列の末尾に達した場合は、先頭(0番目)に戻ります。
- 削除(dequeue):frontの位置にある要素を取り出し、frontを1つ進めます。frontが配列の末尾に達した場合は、先頭に戻ります。
- 満杯判定:(front == 0 && rear == n-1) または (front == rear+1) の場合、キューは満杯です。
C++による実装例
以下は、循環キューをC++で実装したプログラムです。メニュー形式で挿入、削除、表示の操作を選択できます。
#include <iostream>
using namespace std;
int cqueue[5];
int front = -1, rear = -1, n=5;
void insertCQ(int val) {
if ((front == 0 && rear == n-1) || (front == rear+1)) {
cout<<"Queue Overflow \n";
return;
}
if (front == -1) {
front = 0;
rear = 0;
} else {
if (rear == n - 1)
rear = 0;
else
rear = rear + 1;
}
cqueue[rear] = val ;
}
void deleteCQ() {
if (front == -1) {
cout<<"Queue Underflow\n";
return ;
}
cout<<"Element deleted from queue is : "<<cqueue[front]<<endl;
if (front == rear) {
front = -1;
rear = -1;
} else {
if (front == n - 1)
front = 0;
else
front = front + 1;
}
}
void displayCQ() {
int f = front, r = rear;
if (front == -1) {
cout<<"Queue is empty"<<endl;
return;
}
cout<<"Queue elements are :\n";
if (f <= r) {
while (f <= r){
cout<<cqueue[f]<<" ";
f++;
}
} else {
while (f <= n - 1) {
cout<<cqueue[f]<<" ";
f++;
}
f = 0;
while (f <= r) {
cout<<cqueue[f]<<" ";
f++;
}
}
cout<<endl;
}
int main() {
int ch, val;
cout<<"1)Insert\n";
cout<<"2)Delete\n";
cout<<"3)Display\n";
cout<<"4)Exit\n";
do {
cout<<"Enter choice : "<<endl;
cin>>ch;
switch(ch) {
case 1:
cout<<"Input for insertion: "<<endl;
cin>>val;
insertCQ(val);
break;
case 2:
deleteCQ();
break;
case 3:
displayCQ();
break;
case 4:
cout<<"Exit\n";
break;
default: cout<<"Incorrect!\n";
}
} while(ch != 4);
return 0;
}コードの解説
insertCQ関数(挿入処理)
まずオーバーフロー(満杯)のチェックを行い、キューが満杯の場合はメッセージを表示して終了します。キューが空の場合(front == -1)は、frontとrearを0に初期化します。それ以外の場合はrearを1つ進めますが、rearが配列の末尾に達していれば0に戻すことで循環を実現しています。
deleteCQ関数(削除処理)
キューが空の場合(front == -1)はアンダーフローのメッセージを表示します。削除対象の要素を表示した後、frontとrearが同じ位置ならキューは空になったため両者を-1にリセットし、そうでなければfrontを1つ進めます(末尾に達していれば0に戻る)。
displayCQ関数(表示処理)
キューが空の場合はその旨を表示します。frontがrearより小さい場合は単純に順番に表示しますが、循環によってfrontがrearより大きくなっている場合は、末尾まで表示した後に先頭からrearまでを続けて表示することで、正しい順序で全要素を出力できます。
実行結果
上記プログラムの実行例は以下の通りです。要素5、3、2、7、9を挿入した後、3つの要素を削除し、さらに6を挿入して表示しています。
1)Insert 2)Delete 3)Display 4)Exit Enter choice : 1 Input for insertion: 5 Enter choice : 1 Input for insertion: 3 Enter choice : 1 Input for insertion: 2 Enter choice : 1 Input for insertion: 7 Enter choice : 1 Input for insertion: 9 Enter choice : 2 Element deleted from queue is : 5 Enter choice : 2 Element deleted from queue is : 3 Enter choice : 2 Element deleted from queue is : 2 Enter choice : 1 Input for insertion: 6 Enter choice : 3 Queue elements are : 7 9 6 Enter choice : 4 Exit
このように、通常のキューでは一度削除された領域は再利用できませんが、循環キューではrearが配列の先頭に回り込むことで、空いた領域を効率的に使い続けることができます。この特性により、循環キューはOSのタスクスケジューリングやストリーミング処理など、限られたメモリを繰り返し利用する場面で広く活用されています。
-
シーザー暗号を実装するC++プログラム
シーザー暗号とは シーザー暗号は、平文の各文字を別の文字に置き換えることで暗号文を作り出す「単一換字式暗号(モノアルファベット暗号)」の一種です。換字式暗号の中でも最も基本的でシンプルな方式とされています。 この暗号方式は、一般的に「シフト暗号」とも呼ばれます。その考え方は、各アルファベットを0〜25の範囲内の固定した数だけ「ずらした」別のアルファベットに置き換えるというものです。 この方式では、送信者と受信者があらかじめ「秘密のシフト数」を共有しておきます。この0〜25の間の数値が、暗号化の鍵(キー)として機能します。 特に「3文字ずらす」場合には、このシフト暗号を指して「シーザー暗号」と
-
C++でAVL木(AVLツリー)を実装する方法:回転操作とサンプルコードを徹底解説
AVL木とは AVL木(AVL Tree)は、自己平衡型二分探索木(Self-balancing Binary Search Tree)の一種です。すべてのノードにおいて、左部分木と右部分木の高さの差が「1以下」に保たれるという性質を持っています。この平衡条件により、木が片側に偏って成長することを防ぎ、検索・挿入・削除といった操作を常に効率的(O(log n))に行うことができます。 木の回転(Tree Rotation)とは 木の回転とは、要素の順序(ソート順)を崩すことなく木の構造を変更する操作のことです。あるノードを一段上へ移動させ、別のノードを一段下へ移動させることで実現されます。 回