和栈相反,队列是一种先进先出的线性表,他只允许在表的一端进行插入,而在另一端删除元素。在队列中允许插入的一端叫做队尾(队尾入队),允许删除的一端称为队头(队头出队),先进先出。
用链表表示的队列简称为链队列。一个链队列需要两个分别指向队头和队尾的指针。(插入时操作队尾,删除时操作队头-----队列的特性)
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//利用带头节点的单链表实现队列,队头为第一个数据节点
typedef struct Node
{
int data;
struct Node *next;
}Node;//数据节点
typedef struct HNode
{
struct Node *front;//队头指针
struct Node *rear;//队尾指针
}HNode,*PLQueue;//头节点
void InitQueue(PLQueue pl)//队列初始化
{
assert(pl != NULL);
pl->front = NULL;
pl->rear = NULL;
}
bool IsEmpty(PLQueue pl)
{
return pl->front == NULL;
}
//入队
bool Push(PLQueue pl,int val)
{
Node *p = (Node *)malloc(sizeof(Node));
p->data = val;
p->next = NULL;
if(IsEmpty(pl))
{
pl->front = p;
pl->rear = p;
}
else
{
pl->rear->next = p;//将结点p接在原来队尾下一个结点
pl->rear = p;//修改队尾指针
}
return true;
}
//获取队头的值,但不删除
bool GetTop(PLQueue pl,int *rtval)
{
if(IsEmpty(pl))
{
return false;
}
if(rtval != NULL)
{
*rtval = pl->front->data;
}
return true;
}
//获取队头的值,且删除
bool Pop(PLQueue pl,int *rtval)
{
if(IsEmpty(pl))
{
return false;
}
if(rtval != NULL)
{
*rtval = pl->front->data;
}
Node *p = pl->front;
pl->front = p->next;//将头节点指向上一个头结点的下一个结点,此节点变成头结点
free(p);
if(pl->front == NULL) //已经删除最后一个节点
{
pl->rear = NULL;
}
return true;
}
void Destroy(PLQueue pl)
{
Node*p=pl->front;
while(!p)
{
pl->front=p->next;
free(p);
}
if(pl->front == NULL) //已经删除最后一个节点
{
pl->rear = NULL;
}
}
int main()
{
HNode head;
InitQueue(&head);
for(int i=0;i<15;i++)
{
Push(&head,i);
}
int tmp;
while(!IsEmpty(&head))
{
Pop(&head,&tmp);
printf("%d\n",tmp);
}
Destroy(&head);
return 0;
}
循环队列——队列的顺序表示和实现
和顺序表类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次存放从队列头到队列尾的元素之外,尚需附设两个指针front和rear分别指示队列头元素和队列尾元素的位置
顺序表实现环形队列(避免因为实际可用空间并未占满,插入数据时而出现数组越界的情况
front 队头:第一个元素的下标 rear队尾:最后一个元素的下一个位置的下标
队满:(rear+1)%n=front
队空:front==rear
//顺序表实现环形队列
//浪费一个单元不使用,是为了区分队满和队空
#include <stdio.h>
#include <assert.h>
#include<stdlib.h>
#define SIZE 10
typedef struct SQueue
{
int elem[SIZE];
int front;//队头指针,第一个元素的下标
int rear;//队尾指针,最后一个元素的下一个下标,当前可以存放数据的下标
}SQueue,*PSQueue;
void InitQueue(PSQueue ps)
{
assert(ps != NULL);
if(ps == NULL)
{
return ;
}
ps->front = 0;
ps->rear = 0;
}
//判断队空
bool IsEmpty(PSQueue ps)
{
return ps->front==ps->rear;
}
static bool IsFull(PSQueue ps)
{
return (ps->rear+1)%SIZE == ps->front;//
}
//入队
bool Push(PSQueue ps,int val)
{
if(IsFull(ps))
{
return false;
}
ps->elem[ps->rear] = val;
ps->rear = (ps->rear+1)%SIZE;
return true;
}
//获取队头的值,但不删除
bool GetTop(PSQueue ps,int *rtval)
{
if(IsEmpty(ps))
{
return false;
}
if(rtval != NULL)
{
*rtval = ps->elem[ps->front];
}
return true;
}
//获取队头的值,且删除
bool Pop(PSQueue ps,int *rtval)
{
if(IsEmpty(ps))
{
return false;
}
if(rtval!=NULL)
{
*rtval=ps->elem[ps->front];
}
ps->front++;
return true;
}
int main()
{
SQueue head;
InitQueue(&head);
for(int i=0;i<15;i++)
{
Push(&head,i);
}
int tmp;
while(!IsEmpty(&head))
{
Pop(&head,&tmp);
printf("%d\n",tmp);
}
GetTop(&head,&tmp);
printf("%d\n",tmp);
return 0;
}