文章目录
- 队列
 - 1.队列的概念及结构
 - 概念
 - 结构
 
- 2.队列的实现(链式结构)
 - 队列定义
 - 初始化队列
 - 入队
 - 出队
 - 获取队头元素
 - 获取队尾元素
 - 销毁队列
 - 判断队列是否为空
 - 队列有效个数
 
- 完整代码(包含测试代码)
 - Queue.h
 - Queue.c
 - test.c
 
队列
1.队列的概念及结构
概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。
 队列具有先进先出FIFO(First In First Out)
 入队列:进行插入操作的一端称为队尾
 出队列:进行删除操作的一端称为队头
结构
队列也可以数组和链表的结构实现:
队列的顺序结构
入队,直接下标访问,时间复杂度为O(1)
出队,挪动数据覆盖,时间复杂度为O(N)
队列的链式结构
定义两个指针,队头指针指向第一个节点,队尾指针指向尾节点
入队(尾插),时间复杂度为O(1)
出队(头删),时间复杂度为O(1)
所以使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
 
2.队列的实现(链式结构)
首先新建一个工程:
Queue.h(队列的类型定义、接口函数声明、引用的头文件)
 Queue.c(队列接口函数的实现)
 test.c(主函数、测试栈各个接口功能)
完整的代码放在后面(包括测试代码),这里就不会展示测试的效果图。大家可以自己别敲边按测试代码测试。图解会写的很详细的,么么😙
队列定义
typedef int QDataType;
//队列结点结构
typedef struct QlistNode 
{
    QDataType val;//结点元素
    struct QlistNode* next;//结点指针
}QNode;
//队列链式结构
typedef struct Queue
{
    QNode* phead;//队头指针
    QNode* ptail;//队尾指针
    int size;//元素个数
}Queue;
 
初始化队列
初始化这里很讲究的,如果不把两个指针放到结构体里面封装起来,单独来传,那这里很麻烦要用二级指针而且也不太好控制,但是如果用结构体封装起来我们访问这两指针就是访问结构体的成员,要修改就直接修改指向结构体的指针pq就ok了
我们链表那里就讲过了传参的问题,我们实现无头链表的头插头删接口时,因为需要改变头指针的指向两种方法:
1、传二级指针
2、返回值(return)
现在又有了一种方法:
结构体封装起来
//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
 
入队
这个其实就是链表的尾插
//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));//动态申请一个结点
	if (newnode == NULL)//判断结点是否申请成功
	{
		perror("malloc fail");
		return;
	}
	newnode->val = x;
	newnode->next = NULL;
	if (pq->phead==NULL)//队列为空插入
	{
		pq->phead = pq->ptail = newnode;
	}
	else//队列有元素
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
 
出队
这个也就是链表的头删
//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->phead);//队列不能为空
	if (pq->phead->next==NULL)//队列只有一个元素
	{
		pq->ptail = NULL;
	}
	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	pq->size--;
}
 
获取队头元素
//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);//队列不能为空
	return pq->phead->val;
}
 
获取队尾元素
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);//队列不能为空
	return pq->ptail->val;
}
 
销毁队列
//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* pcur = pq->phead;
	while (pcur)
	{
		QNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pcur = NULL;
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
 
判断队列是否为空
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;//pq->phead、pq->ptail两个用哪一个都行
}
 
队列有效个数
//队列有效个数
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
	
}
 
完整代码(包含测试代码)
Queue.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
//队列结点结构
typedef struct QlistNode 
{
    QDataType val;//结点元素
    struct QlistNode* next;//结点指针
}QNode;
//队列链式结构
typedef struct Queue
{
    QNode* phead;//队头指针
    QNode* ptail;//队尾指针
    int size;//元素个数
}Queue;
//初始化队列
void QueueInit(Queue* pq);
//入队
void QueuePush(Queue* pq, QDataType x);
//出队
void QueuePop(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBack(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//队列有效个数
int QueueSize(Queue* pq);
 
Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"queue.h"
//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));//动态申请一个结点
	if (newnode == NULL)//判断结点是否申请成功
	{
		perror("malloc fail");
		return;
	}
	newnode->val = x;
	newnode->next = NULL;
	if (pq->phead==NULL)//队列为空插入
	{
		pq->phead = pq->ptail = newnode;
	}
	else//队列有元素
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->phead);//队列为空中止
	if (pq->phead->next==NULL)//队列只有一个元素
	{
		pq->ptail = NULL;
	}
	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	pq->size--;
}
//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->val;
}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->val;
}
//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* pcur = pq->phead;
	while (pcur)
	{
		QNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pcur = NULL;
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}
//队列有效个数
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
	
}
 
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
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");
	int r = QueueSize(&Q);
	printf("%d ", r);
	//printf("%d ", QueueBack(&Q));
	return 0;
}
                


















