队列,和栈一样,也是一种对数据的"存"和"取"有严格要求的线性存储结构。
队列(Queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。
栈有顺序存储和链式存储,那么队列也有顺序存储和链式存储。
与栈不同的是,队列元素的出列是在队头,即下表为0的位置,那就意味着队列中所有的元素都要向前移动。以保证队头不为空,此时时间复杂度为O(n)。
但是想一想,出队列时为什么元素非要全部移动呢?那么队头不一定要在下表为0的地方。
那么这时当front=rear时,队列就为空队列。
循环队列:把头尾相接的队列叫做循环队列。
#include <stdio.h>
#include<assert.h>
#define _CRT_SECURE_NO_WARNINGS
#define SIZE 10
typedef struct Queue
{
int elem[SIZE];
int front;
int rear;
}Queue;
void InitQueue(Queue* queue)//初始化
{
assert(queue != NULL);
queue->front = 0;
queue->rear = 0;
}
bool IsFull(Queue* queue)
{
return (queue->rear + 1) % SIZE == queue->front;
}
bool Push(Queue* queue, int val)
{
if (IsFull(queue))
{
return false;
}
queue->elem[queue->rear] = val;
queue->rear = (queue->rear + 1) % SIZE;
return true;
}
bool IsEmpty(Queue* queue)
{
return queue->front == queue->rear;
}
bool Pop(Queue* queue, int *rtv)
{
if (IsEmpty(queue))
{
return false;
}
if (rtv != NULL)
{
*rtv = queue->elem[queue->front];
}
queue->front = (queue->front + 1) % SIZE;
return true;
}
void Show(Queue* queue)
{
for (int i = queue->front; i != queue->rear; i = (i + 1) % SIZE)
{
printf("%d ", queue->elem[i]);
}
printf("\n");
}
int GetLength(Queue* queue)
{
return (queue->rear - queue->front + SIZE) % SIZE;
}
void Clear(Queue* queue)
{
queue->front = queue->rear;
}
int main()
{
Queue qu;
InitQueue(&qu);
for (int i = 0; i < 10; i++)
{
Push(&qu, i);//0-8
}
Show(&qu);
int tmp = 0;
Pop(&qu, &tmp);
printf("%d\n", tmp);//0
Pop(&qu, &tmp);
printf("%d\n", tmp);//1
Pop(&qu, &tmp);
printf("%d\n", tmp);//2
Show(&qu);//3-8
int len = GetLength(&qu);
printf("%d\n", len);
return 0;
}
接下来看一下链式队列。
队列的链式存储结构,就是线性表的简单单链表,只能尾进头出。
当队列为空时,front和rear都指向头结点。
#include <stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
#define _CRT_SECURE_NO_WARNINGS
typedef struct QNode
{
int data;
struct QNode *next;
}node;
typedef struct Queue
{
node* front;
node* rear;
int size;
}queue;
//初始化
void QueueInit(queue *q, node *p)
{
assert(q != nullptr&&p != nullptr);
q->front = q->rear = nullptr;
p->next = nullptr;
q->size = 0;
}
int getSize(queue *q)
{
return q->size;
}
bool isEmpty(queue *q)
{
if (q->size == 0)
{
return true;
}
return false;
}
//头插节点
void creatNode(queue *q,int val)
{
QNode * get = (QNode *)malloc(sizeof(QNode));
assert(get != nullptr);
get->data = val;
get->next = nullptr;
if (isEmpty(q))
{
q->front = get;
q->rear = get;
}
else
{
q->rear->next = get;
q->rear = get;
}
q->size++;
}
int getfront(queue *q)
{
if (isEmpty(q))
{
printf("队列已为空");
return 0;
}
return q->front->data;
}
node *del(queue *q)
{
if (isEmpty(q))
{
printf("队列为空,删除错误!\n");
return nullptr;
}
node *temp = q->front;
q->front = temp->next;
q->size--;
return temp;
}
int getrear(queue *q)
{
if (isEmpty(q))
{
printf("队列已为空");
return 0;
}
return q->rear->data;
}
void clear(queue *q)
{
q->front = NULL;
q->rear = NULL;
q->size = 0;
printf("\n队列已清空!\n");
}
int main()
{
queue lq;
node p;
QueueInit(&lq, &p);
srand((unsigned)time(0));
printf("入队30个元素\n");
int i;
for (i = 0; i < 20; i++)
creatNode(&lq, rand() % 300);
printf("队头元素为:%d\n", getfront(&lq));
printf("队尾元素为:%d\n", getrear(&lq));
printf("队列大小为:%d\n", getSize(&lq));
for (i = 0; i < 20; i++)
{
if (i % 10 == 0)
printf("\n");
printf("%3d ", *((int *)del(&lq)));
}
clear(&lq);
return 0;
}