一.队列的定义
1.队列的分类
队列根据存储结构可以分为 顺序队列 和 链式队列
2.队列的结构
①.顺序队列
顺序队列的 front 指向队首元素的前一个下标
②.链式队列
二.顺序队列的基本运算
0.顺序队列的结构体定义
cpp
typedef int data_t;
typedef struct
{
data_t *data; //用数组作为队列的存储空间
int front,rear; // front 为队头前一个位置的下标 , rear 为队列尾部的下标
}sequeue_t;
1.创建一个空队列
cpp
/**
* @description: 创建一个空队列
* @param - : 无
* @return : 创建的队列的指针
*/
sequeue_t *Sequeue_Create(void)
{
sequeue_t *q;
/* 1.为队列分配空间 */
q = (sequeue_t *)malloc(sizeof(sequeue_t));
if(NULL == q)
{
printf("malloc error!\n");
return NULL;
}
/* 2.初始化 front 和 rear 都为 MAXSIZE - 1 */
q->front = q->rear = MAXSIZE - 1;
return q;
}
2.判断队列是否为满
cpp
/**
* @description: 判断队列是否为满
* @param - q : 要操作的队列的指针
* @return : 1为满,0为非满
*/
int Sequeue_Is_Full(sequeue_t *q)
{
if((q->rear + 1) % MAXSIZE == q->front)
return 1;
else
return 0;
}
3.判断队列是否为空
cpp
/**
* @description: 判断队列是否为空
* @param - q : 要操作的队列的指针
* @return : 1为空,其他为非空
*/
int Sequeue_Is_Empty(sequeue_t *q)
{
if(q->rear == q->front)
return 1;
else
return 0;
}
4.入队
cpp
/**
* @description: 入队
* @param - q : 指向队列的指针
* @param - value : 入队元素的值
* @return : 0为成功,其他为失败
*/
int Sequeue_In(sequeue_t *q,data_t value)
{
/* 1.先看队列是否已满 */
if(Sequeue_Is_Full(q))
{
printf("queue is already full!\n");
return -1;
}
/* 2.入队,rear 向后移动,(q->rear+1)%MAXSIZE 是为了保证数组不越界,使该队列成为循环队列 */
q->rear = (q->rear + 1) % MAXSIZE;
/* 3.写入数据 */
q->data[q->rear] = value;
return 0;
}
5.出队
cpp
/**
* @description: 出队
* @param - q : 要操作的队列的指针
* @param - data : 用于存储出队的元素的值
* @return : 0为成功,其他为失败
*/
int Sequeue_Out(sequeue_t *q,data_t *data)
{
/* 1.判断队列是否为空 */
if(Sequeue_Is_Empty(q))
{
printf("sequeue is already empty!\n");
return -1;
}
/* 2.出队 */
q->rear = (q->rear + 1) % MAXSIZE;
*data = q->data[q->front];
return 0;
}
6.打印队列中元素的值
cpp
/**
* @description: 打印出队列所有元素的值
* @param - q : 要操作的队列的指针
*/
void Show_Sequeue(sequeue_t *q)
{
int i = 0;
/* 1.若为空,则退出 */
if(Sequeue_Is_Empty(q))
return ;
/* 2.遍历打印队列中的元素 */
for(i = (q->front+1)%MAXSIZE ; i != (q->rear+1)%MAXSIZE ; i = (i+1)%MAXSIZE)
{
printf("%d\t",q->data[i]);
}
printf("\n");
}
三.链式队列的基本运算
0.链式队列的结构体定义
cpp
typedef int data_t;
/* 1.链表结点 */
typedef struct node
{
data_t data; //结点的数据域
struct node *next; //指向下一个结点的指针
}link_node;
/* 2.队列的队头和队尾指针 */
typedef struct
{
link_node *front,*rear; //front 指向队头元素的前一个结点(即链表的首结点) , rear 指向队尾结点
} linkqueue_t;
1.创建一个空的队列
cpp
/**
* @description: 创建一个空队列
* @param : 无
* @return : 队列的首结点指针
*/
linkqueue_t *Linkqueue_Create(void)
{
linkqueue_t *q;
/* 1.申请队列 front 和 rear 的空间 */
q = (linkqueue_t *)malloc(sizeof(linkqueue_t));
if(NULL == q)
{
printf("malloc error!\n");
return NULL;
}
/* 2.申请链表中头结点的空间 */
q->front = (link_node *)malloc(sizeof(link_node));
if(NULL == q->front)
{
printf("malloc error!\n");
return NULL;
}
q->front->next = NULL; //初始化链表首结点的 next = NULL
q->rear = q->front; //初始化 front 和 rear 都指向链表首结点
return q;
}
2.判断队列是否为空
cpp
/**
* @description: 判断队列是否为空
* @param - q : 要操作的队列的指针
* @return : 1为空 , 0为非空
*/
int Linkqueue_is_empty(linkqueue_t *q)
{
return (q->front == q->rear ? 1 : 0);
}
3.入队
cpp
/**
* @description: 入队
* @param - q : 要操作的队列的指针
* @param - value : 要入队的元素的值
* @return : 0为成功,其他为失败
*/
int Linkqueue_In(linkqueue_t *q,data_t value)
{
link_node *p; //指向新创建的结点
/* 1.创建新的结点 */
p = (link_node *)malloc(sizeof(link_node));
if(NULL == p)
{
printf("malloc error!\n");
return -1;
}
/* 2.初始化新结点 */
p->data = value;
p->next = NULL;
/* 3.向链表进行尾插以实现入队 */
q->rear->next = p;
q->rear = p;
return 0;
}
4.出队
cpp
/**
* @description: 出队 , 使用前需判断队列是否为空
* @param - q : 要操作的队列的指针
* @param - value : 保存出队的元素的值
* @return : 无
*/
void Linkqueue_Out(linkqueue_t *q,data_t *value)
{
link_node *p; //用来指向队头元素的前一个结点
/* 1. p 指向队头的前一个结点( front 就指向了队头元素的前一个结点 ) */
p = q->front;
/* 2. front 向后移动 */
q->front = q->front->next;
/* 3.保存要出队的值 */
*value = q->front->data;
/* 4.释放 p */
free(p);
}
5.打印队列中的结点
cpp
/**
* @description: 打印队列中的数据
* @param - q : 要操作的队列的指针
* @return : 无
*/
void Linkqueue_Show(linkqueue_t *q)
{
link_node *p; //用于指向当前链表的结点
/* 从队头开始遍历打印 */
for(p = q->front->next ; p != NULL ; p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
}