队列的代码实现方式有两种:一种实现方式是连续内存的数组,一种实现方式是离散内存的链表。
而循环队列一般采用连续内存的数组来实现。
1.数组实现方式 / 循环队列
/*************************************************************************
> File Name: queue.c
> Author:
> Mail:
> Created Time: Sat 15 Jul 2023 07:59:42 PM CST
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
// 定义一个队列的数据结构
typedef struct Queue {
int *data;
int size;
int head, tail;
} Queue;
int expand(Queue *q);
// 初始化一个长度为n的队列
Queue *initQueue(int n) {
Queue * q = (Queue *)malloc(sizeof(Queue));
q->data = (int *)malloc(sizeof(int) * n);
q->size = n;
q->head = q->tail = 0;
return q;
}
// 释放空间,养成习惯,一开始就写好
void freeQueue(Queue *q) {
if (!q) {
return ;
}
free(q->data); // 先释放里面开辟的空间
free(q); // 后释放整个队列
return ;
}
// 队列的元素压入
int push(Queue *q, int val) {
if (!q) {
return 0;
}
// 满队
if ((q->tail + 1) % q->size == q->head) {
if (!expand(q)) {
return 0;
}
}
q->data[q->tail] = val;
q->tail = (q->tail + 1) % q->size;
return 1;
}
// 判断队列是否为空
int isEmpty(Queue *q) {
// return !q || q->head == q->tail;
return !(q && q->head != q->tail); // 对偶逻辑
}
// 队列的元素弹出
int pop(Queue *q) {
int ret = q->data[q->head];
q->head = (q->head + 1) % q->size;
return ret;
}
// 打印队列元素
void showQueue(Queue *q) {
if (isEmpty(q)) {
return ;
}
printf("Queue:[");
for (int i = q->head; i != q->tail; i = (i + 1) % q->size) {
i != q->head && printf(", ");
printf("%d", q->data[i]);
}
printf("]\n");
return ;
}
// 队列的扩容
int expand(Queue *q) {
if (!q) {
return 0;
}
int expsize = q->size; // 额外扩容的大小
int *tmp;
while (expsize) {
tmp = (int *)malloc(sizeof(int) * (q->size + expsize));
// realloc 能够在保持旧的内容不变的基础上扩容,但地址离散不适合循环队列
// 这里用malloc实现扩容后仍然是一片连续的地址,方便循环队列的扩容
if (tmp) {
break;
}
expsize >>= 1; // 剩余空间不足,则容量再缩小两倍
}
if (!tmp) { // 如果始终扩容不成功:没有多余的空间,返回0
return 0;
}
// 把队列中的数据搬运到新地址
int i, j;
for (i = q->head, j = 0; i != q->tail; i = (i + 1) % q->size, j++) {
tmp[j] = q->data[i];
}
free(q->data); // 把原来废弃的内存释放掉
q->data = tmp;
q->size += expsize;
q->head = 0;
q->tail = j;
printf("expand successfully~, new size is %d\n", q->size);
return 1;
}
int main () {
srand(time(0));
Queue *q = initQueue(7);
int cnt = 20;
while (cnt--) {
int val = rand() % 100;
int opt = rand() % 4;
switch(opt) {
case 0:
case 1:
case 2:
printf("push %d, res = %s\n", val, push(q, val) ? "SUC" : "ERR");
break;
case 3:
isEmpty(q) ? printf("pop nothing~~\n") : printf("pop %d\n", pop(q));
break;
}
showQueue(q);
}
return 0;
}
2. 链表实现方式
/*************************************************************************
> File Name: listQueue.c
> Author: jby
> Mail:
> Created Time: Sat 15 Jul 2023 09:20:12 PM CST
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
// 结点的数据结构
typedef struct Node {
int val;
struct Node *next;
} Node;
// 队列的数据结构
typedef struct Queue {
Node *head, *tail;
} Queue;
// 节点的初始化
Node *initNode(int val) {
Node *n = (Node *)malloc(sizeof(Node));
n->val = val;
n->next = NULL;
return n;
}
// 释放结点
void freeNode (Node *p) {
if (!p) {
free(p);
}
return ;
}
// 队列初始化
Queue *initQueue() {
Queue *q = (Queue *)malloc(sizeof(Queue));
q->head = q->tail = NULL;
return q;
}
// 释放队列
void freeQueue(Queue *q) {
if (!q) {
return ;
}
Node *p = q->head, *k;
while (p) {
k = p;
p = p->next;
freeNode(k);
}
free(q);
return ;
}
// 队列压入元素
int push(Queue *q, int val) {
if (!q) {
return 0;
}
Node *n = initNode(val);
if (!n) {
return 0;
}
if (q->tail) {
q->tail->next = n;
q->tail = n;
} else {
q->head = q->tail = n;
}
return 1;
}
// 队列判空
int isEmpty(Queue *q) {
return !(q && q->head);
}
// 队列弹出元素
int pop(Queue *q) {
Node *k = q->head;
int tmp = k->val;
q->head = k->next;
freeNode(k);
if (!q->head) {
q->tail = NULL;
}
return tmp;
}
// 打印队列
void showQueue(Queue *q) {
if (!q) {
return ;
}
printf("Queue:[");
Node *p = q->head;
while (p) {
printf("%d->", p->val);
p = p->next;
}
printf("NULL]\n");
return ;
}
int main () {
srand(time(0));
Queue *q = initQueue();
int cnt = 20;
while (cnt--) {
int val = rand() % 20;
int opt = rand() % 4;
switch(opt) {
case 0:
case 1:
case 2:
printf("push %d, res = %s\n", val, push(q, val) ? "SUC":"ERR");
break;
case 3:
isEmpty(q) ? printf("pop nothing~\n") : printf("pop %d\n", pop(q));
break;
}
showQueue(q);
}
freeQueue(q);
return 0;
}