Structure des données - implémentation de la file d'attente

insérez la description de l'image ici

La file d'attente , également appelée file d'attente (file d'attente), type de données abstrait en informatique, est une table linéaire du premier entré, premier sorti (FIFO, First-In-First-Out). Dans des applications spécifiques, il est généralement implémenté avec une liste chaînée ou un tableau. Une file d'attente n'autorise les insertions qu'à l'extrémité arrière (appelée arrière) et les suppressions à l'extrémité avant (appelée avant).
insérez la description de l'image ici

typedef int QDataType;
typedef struct QueueNode
{
    
    
	struct QueueNode* next;
	QDataType data;
}QNode;

Ce code définit une structure nommée QueueNode à l'aide du mot-clé typedef. La structure QueueNode contient deux membres :

Un pointeur vers une autre structure QueueNode, nommée next, utilisée pour représenter le nœud suivant dans la file d'attente.
Une variable nommée data, dont le type de données est QDataType, est utilisée pour représenter les données stockées dans le nœud.
QNode est défini comme un alias de struct QueueNode*, c'est-à-dire que QNode est un pointeur vers une structure QueueNode.

En résumé, ce code définit une structure de nœuds de liste chaînée qui peut être utilisée pour implémenter une structure de données de file d'attente, où chaque nœud contient un élément de données et un pointeur vers le nœud suivant dans la file d'attente.

typedef struct Queue
{
    
    
	QNode* head;
	QNode* tail;
	int size;
}Queue;

Ce code définit une structure nommée Queue à l'aide du mot-clé typedef. La structure Queue contient trois variables membres :

Un pointeur vers une structure QNode, nommé head, utilisé pour représenter le premier nœud de la file d'attente.
Un pointeur vers une structure QNode, nommé tail, utilisé pour représenter le dernier nœud de la file d'attente.
Une variable entière, nommée taille, utilisée pour représenter le nombre de nœuds dans la file d'attente.
Cette structure peut être utilisée pour implémenter une structure de données de file d'attente, où head pointe vers le début de la file d'attente, tail pointe vers la fin de la file d'attente et size enregistre le nombre de nœuds dans la file d'attente. Normalement, l'ajout d'un nœud à la file d'attente fait pointer le pointeur de queue vers le nouveau nœud, et la suppression d'un nœud de la file d'attente fait pointer le pointeur de tête vers le nœud suivant et met à jour la valeur de taille.

//初始化队列
void QueueInit(Queue* q)
{
    
    
	assert(q);
	q->head = q->tail = NULL;
	q->size = 0;
}

Ce code définit une fonction appelée QueueInit, qui est utilisée pour initialiser une file d'attente. La fonction passe un pointeur q pointant vers la structure Queue et utilise la macro assert pour affirmer que q n'est pas NULL.

L'implémentation de la fonction est très simple : affectez NULL aux membres de tête et de queue de q, et affectez 0 au membre de taille, complétant ainsi l'initialisation de la file d'attente. Puisque q est un pointeur, l'opération sur celui-ci dans la fonction consiste en fait à modifier la file d'attente entrante, il n'est donc pas nécessaire de renvoyer une valeur.

// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
    
    
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
	newnode->data = data;
	newnode->next = NULL;

	if (q->head == NULL)
	{
    
    
		assert(q->tail == NULL);
		q->head = q->tail = newnode;
	}
	else
	{
    
    
		q->tail->next = newnode;
		q->tail = newnode;
	}
	q->size++;

Ce code définit une fonction appelée QueuePush qui insère un élément à la fin de la file d'attente. La fonction passe dans un pointeur q pointant vers la structure Queue et les données à insérer.

La mise en œuvre de la fonction se décompose en les étapes suivantes :

Utilisez la fonction malloc pour allouer dynamiquement un espace mémoire avec la taille d'une structure QNode et le transformer en un pointeur newnode pointant vers la structure QNode.
Vérifiez si newnode est vide, s'il est vide, affichez un message d'erreur et revenez.
Affectez le membre de données de newnode aux données entrantes et affectez le membre suivant de newnode à NULL, indiquant que newnode est le dernier nœud de la file d'attente.
Vérifiez si la file d'attente est vide. Si la file d'attente est vide, les membres de tête et de queue de la file d'attente pointent vers newnode, indiquant que newnode est le seul nœud de la file d'attente.
Si la file d'attente n'est pas vide, pointez le pointeur suivant du nœud de queue de la file d'attente vers newnode, indiquant que newnode sera inséré à la fin de la file d'attente, et pointez le pointeur de queue vers newnode, indiquant que newnode est maintenant le dernier nœud dans la file d'attente.
L'ajout de 1 au membre de taille de la file d'attente signifie que le nombre de nœuds dans la file d'attente a augmenté de 1.
La file d'attente étant implémentée par une liste chaînée de pointeurs, il est nécessaire d'effectuer une allocation mémoire dynamique lors de l'insertion d'un nœud, et de modifier les pointeurs des nœuds adjacents.

// 队头出队列
void QueuePop(Queue* q)
{
    
    
	assert(q);
	assert(q->head != NULL);
	QNode* next = q->head->next;
	free(q->head);
	q->head = next;
	if (q->head == NULL)
		q->tail = NULL;
	q->size--;
}

Ce code définit une fonction appelée QueuePop, qui est utilisée pour faire sortir l'élément en tête de la file d'attente de la file d'attente. La fonction passe dans un pointeur q pointant vers la structure Queue.

La mise en œuvre de la fonction se décompose en les étapes suivantes :

Utilisez la macro assert pour vérifier que le q entrant n'est pas vide et que le membre principal de la file d'attente n'est pas NULL. Si la vérification échoue, revenez directement.
Attribuez le pointeur suivant du nœud principal de la file d'attente au suivant, indiquant le nœud suivant en tête de la file d'attente.
Libérez l'espace mémoire occupé par le nœud principal de la file d'attente.
Pointez le pointeur de tête de la file d'attente vers le suivant, ce qui signifie faire sortir le nœud en tête de la file d'attente de la file d'attente.
Si le membre de tête de la file d'attente est NULL, le membre de queue de la file d'attente est également assigné NULL, indiquant que la file d'attente est vide.
Diminuez la taille membre de la file d'attente de 1, ce qui signifie que le nombre de nœuds dans la file d'attente est réduit de 1.
Puisque la file d'attente est implémentée par une liste chaînée de pointeurs, il est nécessaire de libérer l'espace mémoire du nœud et de modifier le pointeur du nœud adjacent lors du popping du nœud.

// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
    
    
	assert(q);
	assert(!QueueEmpty(q));
	return q->head->data;
}

Ce code définit une fonction appelée QueueFront pour obtenir l'élément en tête de la file d'attente. La fonction passe dans un pointeur q pointant vers la structure Queue.

La mise en œuvre de la fonction se décompose en les étapes suivantes :

Utilisez la macro assert pour vérifier que le q passé n'est pas vide et que la file d'attente n'est pas vide. Si la vérification échoue, revenez directement.
Renvoie les données membres du nœud principal de la file d'attente, c'est-à-dire les éléments en tête de la file d'attente.
La file d'attente étant implémentée par une liste chaînée de pointeurs, les éléments en tête de file d'attente peuvent être obtenus en accédant aux données membres du nœud en tête de file d'attente.

// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
    
    
	assert(q);
	assert(!QueueEmpty(q));
	return q->tail->data;
}

Ce code définit une fonction appelée QueueBack pour obtenir l'élément à la fin de la file d'attente. La fonction passe dans un pointeur q pointant vers la structure Queue.

La mise en œuvre de la fonction se décompose en les étapes suivantes :

Utilisez la macro assert pour vérifier que le q passé n'est pas vide et que la file d'attente n'est pas vide. Si la vérification échoue, revenez directement.
Renvoie le membre de données du nœud de queue de la file d'attente, l'élément à la fin de la file d'attente.
Puisque la file d'attente est implémentée par une liste chaînée de pointeurs, les éléments à la fin de la file d'attente peuvent être obtenus en accédant aux données membres du nœud à la fin de la file d'attente.

// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
    
    
	assert(q);
	return q->size;
}

Ce code définit une fonction appelée QueueSize qui obtient le nombre d'éléments valides dans la file d'attente. La fonction passe dans un pointeur q pointant vers la structure Queue.

La mise en œuvre de la fonction est très simple, elle renvoie directement la taille membre de la file d'attente, c'est-à-dire le nombre d'éléments effectifs dans la file d'attente. Étant donné que le membre de taille est mis à jour dynamiquement pendant le fonctionnement de la file d'attente, le nombre d'éléments effectifs dans la file d'attente peut être obtenu via ce membre.

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* q)
{
    
    
	assert(q);
	return q->size == 0;
}

Ce code définit une fonction appelée QueueEmpty, qui est utilisée pour déterminer si la file d'attente est vide. La fonction passe dans un pointeur q pointant vers la structure Queue.

L'implémentation de la fonction est très simple, en vérifiant si le membre de taille de la file d'attente est 0 pour juger si la file d'attente est vide. Renvoie true (résultat non nul) si size est égal à 0 et que la file d'attente est vide, sinon false (0) si la file d'attente n'est pas vide.

// 销毁队列
void QueueDestroy(Queue* q)
{
    
    
	assert(q);
	QNode* cur = q->head;
	while (cur)
	{
    
    
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	q->head = q->tail = NULL;
	q->size = 0;
}

Ce code définit une fonction nommée QueueDestroy pour détruire une file d'attente. La fonction passe dans un pointeur q pointant vers la structure Queue.

La mise en œuvre de la fonction se décompose en les étapes suivantes :

Utilisez la macro assert pour vérifier que le q transmis n'est pas vide.
Attribuez le pointeur de tête de la file d'attente à cur, ce qui signifie détruire les nœuds de la tête de la file d'attente.
Parcourez tous les nœuds de la file d'attente, affectez à chaque fois le prochain pointeur de cur à next et libérez l'espace mémoire occupé par le nœud pointé par cur.
Pointez le pointeur cur vers next, c'est-à-dire déplacez le pointeur vers le nœud suivant et continuez à boucler jusqu'à ce que tous les nœuds soient traversés.
Affectez NULL aux membres de tête et de queue de la file d'attente et affectez 0 au membre de taille de la file d'attente, indiquant que la file d'attente a été détruite.
La file d'attente étant implémentée par une liste chaînée de pointeurs, il est nécessaire de libérer l'espace mémoire occupé par chaque nœud et de déplacer le pointeur vers le nœud suivant lorsque la file d'attente est détruite.

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
typedef struct QueueNode
{
    
    
	struct QueueNode* next;
	QDataType data;
}QNode;
typedef struct Queue
{
    
    
	QNode* head;
	QNode* tail;
	int size;
}Queue;

// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);

//初始化队列
void QueueInit(Queue* q)
{
    
    
	assert(q);
	q->head = q->tail = NULL;
	q->size = 0;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
    
    
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
	newnode->data = data;
	newnode->next = NULL;

	if (q->head == NULL)
	{
    
    
		assert(q->tail == NULL);
		q->head = q->tail = newnode;
	}
	else
	{
    
    
		q->tail->next = newnode;
		q->tail = newnode;
	}
	q->size++;

}
// 队头出队列
void QueuePop(Queue* q)
{
    
    
	assert(q);
	assert(q->head != NULL);
	QNode* next = q->head->next;
	free(q->head);
	q->head = next;
	if (q->head == NULL)
		q->tail = NULL;
	q->size--;
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
    
    
	assert(q);
	assert(!QueueEmpty(q));
	return q->head->data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
    
    
	assert(q);
	assert(!QueueEmpty(q));
	return q->tail->data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
    
    
	assert(q);
	return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* q)
{
    
    
	assert(q);
	return q->size == 0;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
    
    
	assert(q);
	QNode* cur = q->head;
	while (cur)
	{
    
    
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	q->head = q->tail = NULL;
	q->size = 0;
}
int main()
{
    
    
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	QueuePush(&q, 5);
	while (!QueueEmpty(&q))
	{
    
    
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");
	
	QueueDestroy(&q);
	return 0;
}
	

Supongo que te gusta

Origin blog.csdn.net/weixin_51799303/article/details/131355199
Recomendado
Clasificación