005 数据结构_队列——“C”

前言

小留言:哈喽!各位CSDN的uu们,我是你的好友Fan_558,本文是Fan——数据结构与算法学习之路专栏的第五篇文章,本文采用单链表的形式实现队列,希望我的文章可以给您带来一定的帮助

在这里插入图片描述

引入

队列的概念:
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

举一个简单例子,我们在饭堂买饭,此时你是第5号,前面还有1,2,3,4号,当第一个人拿到他的饭后,此时1号从队列中移除,这时又来了一个人,这个只能从队尾开始排。即先进先出

测试用例

已通过如下测试用例,请放心学习

void Test1()
{
	Queue  q;
	QueueInit(&q);
	QueuePush(&q, 1);
	printf("队尾元素为:%d\n", QueueBack(&q));
	QueuePush(&q, 2);
	printf("个数:%d\n", QueueSize(&q));
	printf("队尾元素为:%d\n", QueueBack(&q));
	QueuePush(&q, 3);
	printf("队头元素为:%d\n", QueueFront(&q));
	QueuePush(&q, 4);
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");
	QueueDestroy(&q);
}

void Test2()
{
	Queue  q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	printf("队头元素为:%d\n", QueueFront(&q));
	printf("队尾元素为:%d\n", QueueBack(&q));
	QueuePop(&q);
	QueuePop(&q);
	QueuePop(&q);
	QueuePop(&q);
	printf("个数:%d\n", QueueSize(&q));
	QueueDestroy(&q);
}

int main()
{
	Test1();
	Test2();
	return 0;
}

在这里插入图片描述

实现步骤

1、队列——初始化

解析:这里用两个结构体的原因: 使用结构体可以将相关的变量放在一起,从而使得代码更具可读性 这里把_front与_rear放在一起作为队列的队头与队尾,这一组相关数据用一个Queue类型的结合体联合起来,_next与_data是一个节点的组成成分因此用一个QNode类型的结构体把它们联合起来。 而_front与_rear又是QNode结构体的结构体指针,因此可以用这两个结构体指针来访问QNode结构体的成员变量_next与_data。
// 链式结构:表示队列 
typedef  int QDataType;
//节点
typedef struct QListNode
{
	struct QListNode* _next;
	QDataType _data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* _front;
	QNode* _rear;
}Queue;

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);
	q->_front = NULL;
	q->_rear = NULL;
}

2、队列——销毁

void QueueDestroy(Queue* q)
{
	assert(q);
	QNode* cur = q->_front;						//保存当前节点
	while (cur)
	{
		QNode* next = cur->_next;				//保存当前节点的下一个节点
		free(cur);								//释放当前节点
		cur = next;								//迭代
	}
	q->_front = q->_rear = NULL;
	q->_size = 0;
}

3、队列——判空

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	if (q->_front == NULL)	                    	//为空
	{
		assert(q->_rear);
		return 1;
	}
	else                                           //不为空
	{
		return 0;
	}
}

4、队列——队尾入

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


	//队列为空
	if (q->_front == NULL)
	{
		assert(q->_rear == NULL);				//头尾都指向空
		q->_front = q->_rear = newnode;			//把newnode赋给头尾结构体指针
	}
	//队列不为空
	else
	{
		q->_rear->_next = newnode;				//链接
		q->_rear = newnode;						//更新尾节点
	}
	q->_size++;
}

5、队列——队头出

// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	//一个节点
	if (q->_front->_next == NULL)
	{
		free(q->_front);					//直接释放
		q->_front = q->_rear = NULL;		//置空
	}
	//多个节点
	else
	{
		QNode* cur = q->_front->_next;		//保存头结点的下一个节点
		free(q->_front);					//释放当前节点
		q->_front = cur;					//更新头节点
	}

	q->_size--;

}

6、队列——获取队列队头元素

// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));				//队列不为空
	return q->_front->_data;
}

7、队列——获取队列队尾元素

// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));				//队列不为空
	return q->_rear->_data;
}

小结

学习数据结构需要对结构体传参,结构体成员变量,结构体变量,结构体指针有着深刻地理解,如果有需要的话可以参考我的结构体基础博客里面会一一解答,下一篇博客将会对栈进行实现
最后倘若本文有遗漏疏忽,还需要你指正,以便今后改进!祝你天天开心啦!欢迎到我的博客留言,我会尽力解答,希望能给你一些帮助!

posted @ 2023-05-17 00:30  Fan_558  阅读(3)  评论(0编辑  收藏  举报  来源