注:本文只给出C语言实现代码,涉及到的数据结构相关概念请自行阅读相关书籍或参考其他博文;
①版本1(数据采用顺序表存储方法):
实现顺序存储版队列,即容量大小固定,包含入队、出队、查询队头元素等操作。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/****
* [81, 78, 68, 45, 4 ]
* | |
* head * * * tail **
* |<------size--->| |
* |<------capacity------>|
*/
typedef struct Queue {
int *data; //存储的数据
//head头下标,tail尾下标size队列元素个数
int head, tail, size;
int capacity; //队列容量
} Queue;
Queue *init(int n) { //初始化
Queue *q = (Queue *)malloc(sizeof(Queue));
q->data = (int *)malloc(sizeof(int) * n);
q->capacity = n;
q->head = q->tail = 0; //初始化方式一;方式二可用tail指向队尾元素的下一个位置
q->size = 0;
return q;
}
void clear(Queue *q) { //删除队列
if (q == NULL) return ;
free(q->data);
free(q);
return ;
}
int empty(Queue *q) {//判空
//return q->head == q->tail; //判断队列是否为空
return q->size == 0;
}
int front(Queue *q) {//查询队首元素
return q->data[q->head];
}
int push(Queue *q, int val) {//入队
if (q == NULL) return 0;
if (q->size == q->capacity) {
printf("faile to expand!\n");
return 0;
}
q->data[q->tail++] = val;
if (q->tail == q->capacity) q->tail = 0;
q->size++;
return 1;
}
int pop(Queue *q) {//出队
if (q == NULL) return 0;
if (empty(q)) return 0;
q->head++;
if (q->head == q->capacity) q->head = 0;
q->size--;
return 1;
}
void output(Queue *q) {//打印队列元素
if (q == NULL) return ;
printf("Queue(%d): [", q->size);
for(int i = q->head, j = 0; j < q->size; j++) {
j && printf(",");
printf("%d", q->data[(i + j) % q->capacity]);
}
printf("]\n");
return ;
}
int main(int argc, int **argv) {
srand(time(0));
#define MAX_N 20
Queue *q = init(MAX_N);
for (int i = 0; i < MAX_N; i++) {
int op = rand () % 4;
int val = rand() % 100;
switch(op) {
case 0: case 1: case 2: {
printf("push %d to the Queue = %d\n", val, push(q, val));
} break;
case 3: {
if(!empty(q)) {
printf("pop %d from the Queue = ", front(q));
printf("%d\n", pop(q));
}
} break;
}
output(q);
}
#undef MAX_N
clear(q);
return 0;
}
②版本2(增加自动扩容):
实现顺序存储版队列,即容量大小固定,包含入队、出队、查询队头元素等操作。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define COLOR(a, b) "\033[" #b "m" a "\33[0m"
#define RED(a) COLOR(a, 31)
#define GREEN(a) COLOR(a, 32)
/****
* [81, 78, 68, 45, 4 ]
* | |
* head * * * tail **
* |<------size--->| |
* |<------capacity------>|
*/
typedef struct Queue {
int *data;
int head, tail, size;
int capacity; //队列容量
} Queue;
Queue *init(int n) {
Queue *q = (Queue *)malloc(sizeof(Queue));
q->data = (int *)malloc(sizeof(int) * n);
q->capacity = n;
q->head = q->tail = 0; //初始化方式一;方式二可用tail指向队尾元素的下一个位置
q->size = 0;
return q;
}
void clear(Queue *q) {
if (q == NULL) return ;
free(q->data);
free(q);
return ;
}
int empty(Queue *q) {
//return q->head == q->tail; //判断队列是否为空
return q->size == 0;
}
int front(Queue *q) {
return q->data[q->head];
}
int expand(Queue *q) {
int extr_size = q->capacity;
int *temp;
while (extr_size) {
//可用calloc, 不建议用realloc, 队列是一个有序的序列,拷贝完后进行值拷贝
//realloc拷贝过程可能出问题。因为头指针可能在尾指针后面,拷贝过来处理不好有bug
temp = (int *)malloc(sizeof(int) * (q->capacity + extr_size));
if (temp) break; //申请新内存成功则进行下一步操作;
extr_size >>= 1; //申请新内存不成功则将申请空间减小一半;
}
if (temp == NULL) return 0;
//将数据拷贝到新申请的空间
for (int i = q->head, j = 0; j < q->size; j++) {
temp[j] = q->data[(i + j) % q->capacity];
}
free(q->data);//释放旧内存空间;
q->data = temp;
q->head = 0, q->tail = q->size;
q->capacity += extr_size;
printf(GREEN("expand successfully! the size is %d\n"), q->capacity);
return 1;
}
int push(Queue *q, int val) {
if (q == NULL) return 0;
if (q->size == q->capacity) {
if (!expand(q)) {
printf(RED("faile to expand!\n"));
return 0;
}
}
q->data[q->tail++] = val;
if (q->tail == q->capacity) q->tail = 0;
q->size++;
return 1;
}
int pop(Queue *q) {
if (q == NULL) return 0;
if (empty(q)) return 0;
q->head++;
if (q->head == q->capacity) q->head = 0;
q->size--;
return 1;
}
void output(Queue *q) {
if (q == NULL) return ;
printf("Queue(%d): [", q->size);
for(int i = q->head, j = 0; j < q->size; j++) {
j && printf(",");
printf("%d", q->data[(i + j) % q->capacity]);
}
printf("]\n");
return ;
}
int main(int argc, int **argv) {
srand(time(0));
#define MAX_N 20
Queue *q = init(1);
for (int i = 0; i < MAX_N; i++) {
int op = rand () % 4;
int val = rand() % 100;
switch(op) {
case 0: case 1: case 2: {
printf("push %d to the Queue = %d\n", val, push(q, val));
} break;
case 3: {
if(!empty(q)) {
printf("pop %d from the Queue = ", front(q));
printf("%d\n", pop(q));
}
} break;
}
output(q);
}
#undef MAX_N
clear(q);
return 0;
}
③ 版本3(数据采用链式存储方法):
实现链式存储版队列,即容量根据数据量自动调整,包含入队、出队、查询队头元素等操作。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
typedef struct Queue {
Node head, *tail;//虚拟头节点
int length;//链队列元素个数
} Queue;
Node *getNewNode(int);
Queue *init_queue();
void clear_node(Node *);
void clear(Queue *);
int push(Queue *, int);
int pop(Queue *);
int empty(Queue *);
int front(Queue *);
void output(Queue *);
Node *getNewNode(int val) {
Node *node = (Node *)malloc(sizeof(Node));
node->data = val;
node->next = NULL;
return node;
}
Queue *init_queue() {
Queue *q = (Queue *)malloc(sizeof(Queue));
q->head.next = NULL;
q->tail = &(q->head);
q->length = 0;
return q;
}
int empty(Queue *q) {
return q->length == 0;//判断队列是否为空,用q->tail == NULL,栈空的时候会出错
}
int front(Queue *q) {
return q->head.next->data;
}
int push(Queue *q, int val) {
if (q == NULL) return 0;
Node *temp = getNewNode(val);
q->tail->next = temp;
q->tail = temp;
q->length += 1;
return 1;
}
int pop(Queue *q) {
if (q == NULL) return 0;
if (empty(q)) return 0;
Node *temp = q->head.next;
q->head.next = temp->next;
clear_node(temp);
q->length -= 1;
if (q->length == 0) q->tail = &(q->head); //没有改句在队列只有一个节点的时候删除了该节点会丢失tail
return 1;
}
void clear_node(Node *node) {
if (node == NULL) return;
free(node);
return;
}
void clear(Queue *q) {
if (q == NULL) return;
Node *p = q->head.next, *temp;
while (p != NULL) {
temp = p->next;
clear_node(p);
p = temp;
}
free(q);
return ;
}
void output(Queue *q) {
if (q == NULL) return;
printf("Queue(%d) : [", q->length);
for (Node *p = q->head.next; p != NULL; p = p->next) {
p != q->head.next && printf(", ");
printf("%d", p->data);
}
printf("]\n");
return;
}
int main() {
srand(time(0));
Queue *q = init_queue();
#define MAX_OP 20
for (int i = 0; i < MAX_OP; i++) {
int op = rand() % 4;
int val = rand() % 100;
switch(op) {
case 1:
case 2: {
printf("push %d to the Queue = %d\n", val, push(q, val));
} break;
case 0:
case 3: {
if(!empty(q)) {
printf("pop %d from the Queue = ", front(q));
printf("%d\n", pop(q));
}
} break;
}
output(q), printf("\n");
}
#undef MAX_OP
clear(q);
return 0;
}