目录

一、队列概述

1、队列的基本概念

2、队列的应用

3、队列的具体实现

二、顺序队列

1、顺序队列的描述

2、关于顺序队列操作的思考

3、循环队列的概念

4、循环顺序队列的初始化

5、获取顺序队列的长度(实际存储的元素的个数)

6、判断顺序队列是否为空

7、判断顺序队列是否为满

8、入队

9、顺序队列打印

10、出队

11、代码展示

三、链式队列

代码展示


一、队列概述

1、队列的基本概念

        队列是一种基**先进先出(FIFO)**的数据结构,是一种只能在一端进行插入,在另一端进行删除操作的特殊线性表,它按照先进先出的原则存储数据,先进入的数据,在读取数据时先读被读出来。

2、队列的应用

  • 举例1:排队系统的实现
  • 举例2:使用循环队列存储网络摄像头的数据帧(图像数据)

3、队列的具体实现

  • 顺序队列
  • 链队列

二、顺序队列

在实现顺序队列之前,我们先来看一看对于顺序队列的操作:

顺序队列可以使用一维数组实现,在顺序队列中有两个指针,一个指针front指向队列的队首(数组的第0个元素),一个指针rear指向队列的队尾(最后一个放入队列的元素)。

1、顺序队列的描述

#define FALSE -1
#define TRUE  0
#define QUEUE_INIT_LEN 100 
#define QUEUEINCREMENT 10

typedef int ElemType;
typedef unsigned int uint;

typedef struct SqQueue {
	ElemType* base;//存储堆上元素的地址空间的首地址
	uint front;//队首指针
	uint rear;//队尾指针 
}SqQueue;

2、关于顺序队列操作的思考

  • 如果对顺序队列进行出队操作,队首指针该如何移动?
    • 队首指针往后移动
  • 对顺序队列进行出队操作后,被出队的元素所占用的空间怎处理?
    • 只能暂时空着,等待下次循环使用

  • 如何判断顺序队列是否为满,是否为空呢?
    • 判断队列为满和空的依据都是front == rear,因此会有冲突
  • 如何判断队列是否溢出呢?
    • 当front为0,rear等于队列最大长度时为真溢出

当front不为0,rear等于队列最大长度时为假溢出

3、循环队列的概念

队列上的各个元素逻辑上形成一个圆环状。

如何判断队列是否为满呢?

  • 将队列上的一个位置作为空闲位置
  • 假设队列的长度为M,当 (rear + 1)% M == font时,认为队列为满

4、循环顺序队列的初始化

/* 
* @brief 初始化一个顺序队列 
* @param len 顺序队列的初始化长度(可以存储的元素的最大个数) 
* @return 返回初始化的顺序队列 * */
SqQueue SqQueue_init(uint size) {
	SqQueue s ;
	s.base =(ElemType*)malloc(sizeof(ElemType) * size);
	s.front = 0;
	s.rear = 0;
	return s;
}

5、获取顺序队列的长度(实际存储的元素的个数)


/*
* @brief 获取顺序队列的长度 
* @param s 顺序队列 
* @return 顺序队列的长度 
* */
int SqQueue_length(SqQueue s,uint size) {
	return (s.rear - s.front+size)%size;
}

6、判断顺序队列是否为空

/* 
* @brief 判断顺序队列是否为空 
* @param 顺序队列 
* @return 为空返回TRUE,不为空返回FALSE 
* */
int is_empty(SqQueue s) {
	if (s.front==s.rear)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

7、判断顺序队列是否为满

/* 
* @brief 判断顺序队列是否为满 
* @param 顺序队列 
* @return 为满返回TRUE,不为满返回FALSE 
* */
int is_full(SqQueue s) {
	if ((s.rear+1)% QUEUE_INIT_LEN==s.front)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

8、入队

/* 
* @brief 循环顺序队列入队 
* @param data 需要入队得元素
* @return 成功返回TRUE, 失败返回FALSE 
* */
int EnQueue(SqQueue *s,ElemType data) {
	if (s==NULL)
	{
		printf("[%s %d] s is NULL"__FUNCTION__,__LINE__);
		return FALSE;
	}
	if (is_full(*s) == TRUE)
	{
		//判断队列是否已满
		printf("The queue is full");
		return FALSE;
	}
	s->base[s->rear] = data;
	s->rear = (s->rear + 1) % QUEUE_INIT_LEN;
	return TRUE;
}

9、顺序队列打印

/* 
* @brief 输出顺序队列中的元素 
*@param s 需要输出顺序队列 
* @return 成功返回TRUE,失败返回FALSE 
* */
int printf_SqQueue(SqQueue s) {
	if (is_empty(s)==TRUE)
	{
		printf("[%s %d] s is NULL"__FUNCTION__, __LINE__);
		return FALSE;
	}
	int t=s.front;
	while (t != s.rear) {
		printf("%d ",s.base[t]);
		t = (t + 1) % QUEUE_INIT_LEN;
	}
	printf("\n");
	return TRUE;
}

10、出队

/*
* @brief 循环顺序队列出队
* @param data 存储出队元素的指针 
* @return 成功返回TRUE, 失败返回FALSE
* */
int DeQueue(SqQueue* s, ElemType* data) {
	if (s == NULL)
	{
		printf("[%s %d] s is NULL"__FUNCTION__, __LINE__);
		return FALSE;
	}
	if (is_empty(*s) == TRUE)
	{
		//判断队列是否为空
		printf("The queue is full");
		return FALSE;
	}
	*data = s->base[s->front];
	s->front=(s->front+1)% QUEUE_INIT_LEN;
	return TRUE;
}

11、代码展示

#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>

#define FALSE -1
#define TRUE  0
#define QUEUE_INIT_LEN 100 
#define QUEUEINCREMENT 10

typedef int ElemType;
typedef unsigned int uint;

typedef struct SqQueue {
	ElemType* base;//存储堆上元素的地址空间的首地址
	uint front;//队首指针
	uint rear;//队尾指针 
}SqQueue;
/* 
* @brief 初始化一个顺序队列 
* @param len 顺序队列的初始化长度(可以存储的元素的最大个数) 
* @return 返回初始化的顺序队列 * */
SqQueue SqQueue_init(uint size) {
	SqQueue s ;
	s.base =(ElemType*)malloc(sizeof(ElemType) * size);
	s.front = 0;
	s.rear = 0;
	return s;
}

/*
* @brief 获取顺序队列的长度 
* @param s 顺序队列 
* @return 顺序队列的长度 
* */
int SqQueue_length(SqQueue s,uint size) {
	return (s.rear - s.front+size)%size;
}

/* 
* @brief 判断顺序队列是否为空 
* @param 顺序队列 
* @return 为空返回TRUE,不为空返回FALSE 
* */
int is_empty(SqQueue s) {
	if (s.front==s.rear)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
/* 
* @brief 判断顺序队列是否为满 
* @param 顺序队列 
* @return 为满返回TRUE,不为满返回FALSE 
* */
int is_full(SqQueue s) {
	if ((s.rear+1)% QUEUE_INIT_LEN==s.front)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
/* 
* @brief 循环顺序队列入队 
* @param data 需要入队得元素
* @return 成功返回TRUE, 失败返回FALSE 
* */
int EnQueue(SqQueue *s,ElemType data) {
	if (s==NULL)
	{
		printf("[%s %d] s is NULL"__FUNCTION__,__LINE__);
		return FALSE;
	}
	if (is_full(*s) == TRUE)
	{
		//判断队列是否已满
		printf("The queue is full");
		return FALSE;
	}
	s->base[s->rear] = data;
	s->rear = (s->rear + 1) % QUEUE_INIT_LEN;
	return TRUE;
}
/* 
* @brief 输出顺序队列中的元素 
*@param s 需要输出顺序队列 
* @return 成功返回TRUE,失败返回FALSE 
* */
int printf_SqQueue(SqQueue s) {
	if (is_empty(s)==TRUE)
	{
		printf("[%s %d] s is NULL"__FUNCTION__, __LINE__);
		return FALSE;
	}
	int t=s.front;
	while (t != s.rear) {
		printf("%d ",s.base[t]);
		t = (t + 1) % QUEUE_INIT_LEN;
	}
	printf("\n");
	return TRUE;
}

/*
* @brief 循环顺序队列出队
* @param data 存储出队元素的指针 
* @return 成功返回TRUE, 失败返回FALSE
* */
int DeQueue(SqQueue* s, ElemType* data) {
	if (s == NULL)
	{
		printf("[%s %d] s is NULL"__FUNCTION__, __LINE__);
		return FALSE;
	}
	if (is_empty(*s) == TRUE)
	{
		//判断队列是否为空
		printf("The queue is full");
		return FALSE;
	}
	*data = s->base[s->front];
	s->front=(s->front+1)% QUEUE_INIT_LEN;
	return TRUE;
}

int main() {
	SqQueue s;
	s = SqQueue_init(QUEUE_INIT_LEN);
	srand(time(NULL));
	for (int i = 0; i < 20; i++)
	{
		int data = rand() % 100;
		EnQueue(&s, data);
	}
	printf("输出队列");
	printf_SqQueue(s);
	printf("出队");
	while (is_empty(s)!=TRUE) {
		int data = 0;
		DeQueue(&s,&data);
		printf("%d ",data);
	}

	if (is_empty(s)==TRUE)
	{
		printf("empty");
	}
	return 0;
}

三、链式队列

链式队列可以理解为对单向链表的操作,入队就是单向链表的尾插法,出队则需要销毁第一个数据结点(类似删除链表上的第一个数据结点)。

代码展示

#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>

#define FALSE -1
#define TRUE  0
#define QUEUE_INIT_LEN 100 
#define QUEUEINCREMENT 10

typedef int ElemType;
typedef unsigned int uint;
//定义一个结构体存储指向链表的指针
typedef struct LNode {
	ElemType data;
	struct LNode* next;
}LNode,*LinkNode;


//定义链表上的一个结点
typedef struct Queue {
	LNode* front; //队首指针
	LNode* rear; //队尾指针
}Queue,*LinkQueue;

/*
* @brief 初始化一个链式队列 
* @return 代表链式队列的结构体 
* */
LinkQueue queue_init() {
	LinkQueue q=(LinkQueue)malloc(sizeof(Queue));;
	q->front = NULL;
	q->rear = NULL; 
	return q;
}
/* 
* @brief 入队 
* @param L 链式队列的指针 
* @param data 需要插入的元素 
* @return 成功返回TRUE,失败返回FALSE 
* */ 
int EnQueue(LinkQueue L, ElemType data) {
	if (NULL == L) {
		printf("[%s %d] L pointer is NULL ...\n", __FUNCTION__, __LINE__);
		return FALSE;
	}
	LNode* tmp = (LNode*)malloc(sizeof(LNode));
	tmp->data = data;
	tmp->next = NULL;
	if (L->front==NULL||L->front->next==NULL)
	{
		L->front = tmp;
		L->rear = tmp;
	}
	L->rear->next = tmp;
	L->rear = tmp;
	return TRUE;
}
/*
* @brief 打印链式队列中的元素 
* @param L 链式队列结构体 
* @return 
* */
int queue_printf(LinkQueue que) {
	if (NULL == que||NULL==que->front) {
		printf("[%s %d] L pointer is NULL ...\n", __FUNCTION__, __LINE__);
		return FALSE;
	}
	LNode* tmp=que->front;
	while (tmp!=NULL) {
		printf("%d ", tmp->data);
		tmp = tmp->next;
	}
	printf("\n");
	return TRUE;
}
/* 
* @brief 出队 
* @param L 链式队列的指针 
* @param data 需要出队的元素 
* @return 成功返回TRUE,失败返回FALSE 
* */
int DeQueue(LinkQueue que, ElemType* data) {
	if (NULL == que || NULL == que->front) {
		printf("[%s %d] L pointer is NULL ...\n", __FUNCTION__, __LINE__);
		return FALSE;
	}
	LNode* tmp = que->front;
	*data = tmp->data;
	tmp = tmp->next;
	free(que);
	que->front = tmp;
	return TRUE;
}

int main() {
	srand(time(NULL));
	LinkQueue que;
	que= queue_init();
	for (int i = 0; i < 10; i++)
	{
		int data = rand() % 100;
		EnQueue(que, data);
	}
	queue_printf(que);
	int data;
	DeQueue(que, &data);
	queue_printf(que);
	printf("%d ", data);
}

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐