【データ構造とアルゴリズム】キューの認識と循環キューの実装

前回の記事に引き続き、スタックに関する知識内容を学びました。次に、スタックに似たもう一つの特殊な線形テーブルであるキューについて学びましょう。この記事の目的は、スタックの概念を理解して理解することです。キューを作成し、循環キューを実現します

目次

1. 待ち行列を知る

1. キューの概念

2. キューの実装

第二に、循環キューを実現する

1. 構造体のフォーマットと初期化

2. キューの最後に要素を (キューに) 挿入します。

3. キューの先頭のデータを削除(キュー外)

4. 印刷する

5. キューをクリアし、キューの先頭の要素を返し、キュー内の要素の数を返します。

3. 完全なコード実装

要約する


1. 待ち行列を知る

1. キューの概念

キュー: 一方の端でデータを挿入し、もう一方の端でデータを削除することのみを許可する特殊な線形テーブルです。キューには先入れ先出しの特性があります。キューの最後にデータを挿入することをキューに入ると言います。キューの先頭のデータを削除することをデキューと呼びます。

写真が示すように:

2. キューの実装

キューは、順次リストとリンク リストの 2 つの方法で実装でき、キューは循環キューと非循環キューに分けられます。

区別する:

1. 非循環キューの場合、配列の構造を使用すると、キューを配列の先頭に出力すると効率が低下するため、リンク リストの構造を使用することをお勧めします。

2. 循環キューを使用する場合、配列を使用する方が便利で簡潔です。唯一の欠点は、循環キューに配列を使用する場合、静的配列のみであることです。動的な循環キューは形成できません。もちろん、循環リンク リストを使用することもできます。

第二に、循環キューを実現する

配列の構造を使用して循環キューを実装します。

1. 構造体のフォーマットと初期化

コードは以下のように表示されます:

#define MAXSIZE 11//表示的是数组的元素个数,多一个1,是为了留给rear空间的
typedef struct SqQueue {
	int data[MAXSIZE];
	int front;//队头
	int rear;//队尾   front 和 rear 就是指针(类似)
}SqQueue;

//初始化队列
void InitQueue(SqQueue* ps) {
	//初始化队列只需要队头队尾都为0   表示下标起始位置
	ps->front = ps->rear = 0;
}

実際には静的配列を使用しており、この方法でのみ循環キューを実現できます。動的配列の場合、循環効果は達成できず、定義された MAXSIZE サイズは 11 であり、値を保存しません。記号として。

2. キューの最後に要素を (キューに) 挿入します。

最も重要なポイントは理解することです 

(rear+1)%MAXSIZE==front キューがフルかどうかを判定するフラグです

写真が示すように:

 コードは以下のように表示されます:

//队尾插入元素
void EnQueue(SqQueue* ps,int data) {
	//插入的时候先进行判满
	if ((ps->rear + 1) % MAXSIZE == ps->front) {//最多存储MAXSIZE-1个元素
		//表示已经满了
		perror("队列已经满了,无法加入新元素\n");
		exit(-1);//stdlib.h  头文件里面的
	}
	ps->data[ps->rear] = data;
	ps->rear = (ps->rear + 1) % MAXSIZE;
}

3. キューの先頭のデータを削除(キュー外)

写真が示すように:

コードは以下のように表示されます:

//队头出队
//只需要移动指针位置即可
void OutQueue(SqQueue* ps, int* data) {
	//出队先判别是否为空
	if (ps->rear == ps->front) {
		perror("为空队列,无法出队\n");
		exit(-1);
	}
	*data = ps->data[ps->front];
	ps->front = (ps->front + 1) % MAXSIZE;
	//不需要整体移动只要将队头指针后移就可以
}

4. 印刷する

写真が示すように:

コードは以下のように表示されます:

//遍历打印元素
void PrintQueue(SqQueue* ps) {
	int i = 0;
	printf("Queue->");
	while ((i + ps->front)%MAXSIZE != ps->rear) {
		//从front的队头位置开始,i从0开始 ++一直到等于rear结束
		printf("%d->", ps->data[i + ps->front]);
		i = (i + 1) % MAXSIZE;
	}
	printf("NULL\n");
}

5. キューをクリアし、キューの先頭の要素を返し、キュー内の要素の数を返します。

コードは以下のように表示されます:

//将队列清空

void ClearQueue(SqQueue* ps) {
	ps->front = ps->rear = 0;
}

//返回队头元素
void GetHead(SqQueue* ps, int* data) {
	if (ps->front == ps->rear) {
		perror("为空队列\n");
		exit(-1);
	}
	*data = ps->data[ps->front];
}

//返回队列中的元素个数

int CountSqQueue(SqQueue* ps) {
	return (ps->rear - ps->front + MAXSIZE) % MAXSIZE;
}

3. 完全なコード実装

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#include<stdlib.h>
//构建的是循环队列,是使用数组的形式,完成的循环队列

#define MAXSIZE 11//表示的是数组的元素个数,多一个1,是为了留给rear空间的
typedef struct SqQueue {
	int data[MAXSIZE];
	int front;//队头
	int rear;//队尾   front 和 rear 就是指针(类似)
}SqQueue;

//初始化队列
void InitQueue(SqQueue* ps) {
	//初始化队列只需要队头队尾都为0   表示下标起始位置
	ps->front = ps->rear = 0;
}

//将队列清空

void ClearQueue(SqQueue* ps) {
	ps->front = ps->rear = 0;
}

//队尾插入元素
void EnQueue(SqQueue* ps,int data) {
	//插入的时候先进行判满
	if ((ps->rear + 1) % MAXSIZE == ps->front) {//最多存储MAXSIZE-1个元素
		//表示已经满了
		perror("队列已经满了,无法加入新元素\n");
		exit(-1);//stdlib.h  头文件里面的
	}
	ps->data[ps->rear] = data;
	ps->rear = (ps->rear + 1) % MAXSIZE;
}

//队头出队
//只需要移动指针位置即可
void OutQueue(SqQueue* ps, int* data) {
	//出队先判别是否为空
	if (ps->rear == ps->front) {
		perror("为空队列,无法出队\n");
		exit(-1);
	}
	*data = ps->data[ps->front];
	ps->front = (ps->front + 1) % MAXSIZE;
	//不需要整体移动只要将队头指针后移就可以
}
//遍历打印元素
void PrintQueue(SqQueue* ps) {
	int i = 0;
	printf("Queue->");
	while ((i + ps->front)%MAXSIZE != ps->rear) {
		//从front的队头位置开始,i从0开始 ++一直到等于rear结束
		printf("%d->", ps->data[i + ps->front]);
		i = (i + 1) % MAXSIZE;
	}
	printf("NULL\n");
}
//返回队头元素
void GetHead(SqQueue* ps, int* data) {
	if (ps->front == ps->rear) {
		perror("为空队列\n");
		exit(-1);
	}
	*data = ps->data[ps->front];
}

//返回队列中的元素个数

int CountSqQueue(SqQueue* ps) {
	return (ps->rear - ps->front + MAXSIZE) % MAXSIZE;
}

int main() {
	SqQueue Q;
	InitQueue(&Q);
	EnQueue(&Q, 1);
	EnQueue(&Q, 2);
	EnQueue(&Q, 3);
	EnQueue(&Q, 4);
	EnQueue(&Q, 5);
	PrintQueue(&Q);
	int a = 0;
	OutQueue(&Q, &a);
	PrintQueue(&Q);
	EnQueue(&Q, 1);
	EnQueue(&Q, 2);
	//EnQueue(&Q, 3);
	EnQueue(&Q, 4);
	EnQueue(&Q, 4);
	EnQueue(&Q, 5);
	EnQueue(&Q, 5);
	PrintQueue(&Q);
}

要約する

この記事では、キューの新しい概念について説明します。また、配列の構造を通じて循環キューを実装します。循環キューを実装するこの方法は、比較的単純で理解しやすいです。主なことは、たとえば、MAXSIZE に余分なスペースが必要な理由を理解することです。 11 に設定します。空の判定、完全な判定、操作があります。これが最も重要です。

空判定:リア==フロント

ジャッジメントフル:(リア+1)%MAXSIZE==フロント

キュー要素の数を取得します: (rear-front+MAXSIZE)%MAXSIZE

フロント、リア、i の次の位置を取得する方法:

例: リア=(リア+1)%MAXSIZE

おすすめ

転載: blog.csdn.net/qq_63319459/article/details/128802057