队列
队列:先进先出 FIFO—first in first out
队列的结构定义(线性结构)
结构定义
typedef struct Queue {
int *data;
int head, tail, length;
} Queue;
length
队列的最大长度;队列的容量大小。
head
队首元素的下标 tail
队未元素的下标;
int *data
储存连续内存首地址;
队列的操作
初始化
Queue *init(int n) {
Queue *q =(Queue *)malloc(sizeof(Queue));
q->data = (int *)malloc(sizeof(int) * n);
q->length = n;
q->head = q->tail = 0;
}
q->data = (int *)malloc(sizeof(int) * n)
开辟n*sizeof(int)大小的一连续空间,将其强转成int类型,并传给q->data
.
清除
void clear(Queue *q) {
if (q == NULL) return ;
free(q->data);
free(q);
return ;
}
判空
int empty(Queue *q) {
return q->head == q->tail;
}
通过下标判断,也可以通过其它方法。
出队
int pop(Queue *q) {
if (q == NULL) return 0;
if (empty(q)) return 0;
q->head += 1;
return 1;
}
出队时需要判空操作,向后移动 head
即可。
入队
int push(Queue *q, int val) {
if (q == NULL) return 0;
if (q->tail == q->length) return 0;
q->data[q->tail++] = val;
return 1;
}
返回队首元素
int front(Queue) {
return q->data[q->head];
}
打印
void output(Queue *q) {
printf("Queue: [");
for (int i = q->head; i < q->tail; i++) {
i != q->head && printf(" ");
printf("%d", q->data[i]);
}
printf("]\n");
return ;
}
队列的假溢出
当下表 t a i l = l e n g t h tail=length tail=length 出现伪满的情况。 实际上可能出现 队列元素的个数< length
此时,可以使用循环队列或者链表队列。
完整代码1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef struct Queue {
int *data;
int head, tail, length;
} Queue;
Queue *init(int n) {
Queue *q =(Queue *)malloc(sizeof(Queue));
q->data = (int *)malloc(sizeof(int) * n);
q->length = n;
q->head = q->tail = 0;
}
int empty(Queue *q) {
return q->head == q->tail;
}
int front(Queue *q) {
return q->data[q->head];
}
int push(Queue *q, int val) {
if (q == NULL) return 0;
if (q->tail == q->length) return 0;
q->data[q->tail++] = val;
return 1;
}
int pop(Queue *q) {
if (q == NULL) return 0;
if (empty(q)) return 0;
q->head += 1;
return 1;
}
void clear(Queue *q) {
if (q == NULL) return ;
free(q->data);
free(q);
return ;
}
void output(Queue *q) {
printf("Queue: [");
for (int i = q->head; i < q->tail; i++) {
i != q->head && printf(" ");
printf("%d", q->data[i]);
}
printf("]\n");
return ;
}
int main() {
srand(time(0));
#define MAX_OP 20
Queue *q = init(10);
for (int i = 0; i < MAX_OP; i++){
int op = rand() % 4;
int val = rand() % 100;
switch (op) {
case 0:
case 1:
case 2: {
printf("push %d to Queue = %d\n", val, push(q, val));
}break;
case 3: {
if (empty(q)) {
printf("fail to pop a item!\n");
} else {
printf("success to pop a item : %d\n", front(q));
pop(q);
}
}break;
}
output(q), printf("\n");
}
return 0;
}
循环队列
循环队列的结构
typedef struct Queue {
int *data;
int head, tail, length, count;
} Queue;
相对于常规的队列仅添加了 计数器count,用于数据的判空; 滑动数据使得tail绕到head的前面(使用取余运算%)。
初始化
Queue *init(int n) {
Queue *q =(Queue *)malloc(sizeof(Queue));
q->data = (int *)malloc(sizeof(int) * n);
q->length = n;
q->head = q->tail = 0;
q->count = 0;
}
判空
int empty(Queue *q) {
return q->count == 0;
}
循环队列的入队
int push(Queue *q, int val) {
if (q == NULL) return 0;
if (q->count == q->length) {
if(!expand(q)) return 0;
printf("success to expand ! the size = %d\n", q->length);
};
q->data[q->tail++] = val;
if(q->tail == q->length) q->tail = 0;
q->count += 1;
return 1;
}
当q->tail = 1->length
是需要将 q->tail
重置零,即q->tail = 0
或者 q->tail %= l->length
。
扩容
int expand(Queue *q) {
int *p;
int extr_size = q->length;
while(extr_size){
p = (int *)malloc(sizeof(int) *(q->length + extr_size));
if (p != NULL) break;
extr_size >>= 1;
}
if(p == NULL) return 0;
for (int i = q->length, j = 0; j < q->count; j++) {
p[j] = q->data[(i + j) % q->length];
}
free(q->data);
q->data = p;
q->head = 0;
q->tail = q->count;
q->length += extr_size;
return 1;
}
循环扩容,连续减半扩容大小,以保证动态申请内存的成功。由于结构是循环的,head不一定是零位,如果使用realloc将会产生对后续内存的改动。
循环队列的出队
int pop(Queue *q) {
if (q == NULL) return 0;
if (empty(q)) return 0;
q->head += 1;
if(q->head == q->length) q->head = 0;
q->count -= 1;
return 1;
}
循化队列的打印
void output(Queue *q) {
printf("Queue: [");
for (int i = q->head, j = 0; j < q->count; j++) { //j偏移量
j && printf(" ");
printf("%d", q->data[(i + j) % q->length]);
}
printf("]\n");
return ;
}
完整代码2
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef struct Queue {
int *data;
int head, tail, length, count;
} Queue;
Queue *init(int n) {
Queue *q =(Queue *)malloc(sizeof(Queue));
q->data = (int *)malloc(sizeof(int) * n);
q->length = n;
q->head = q->tail = 0;
q->count = 0;
}
int empty(Queue *q) {
return q->count == 0;
}
int front(Queue *q) {
return q->data[q->head];
}
int expand(Queue *q) {
int *p;
int extr_size = q->length;
while(extr_size){
p = (int *)malloc(sizeof(int) *(q->length + extr_size));
if (p != NULL) break;
extr_size >>= 1;
}
if(p == NULL) return 0;
for (int i = q->length, j = 0; j<q->count; j++) {
p[j] = q->data[(i + j) % q->length];
}
free(q->data);
q->data = p;
q->head = 0;
q->tail = q->count;
q->length += extr_size;
return 1;
}
int push(Queue *q, int val) {
if (q == NULL) return 0;
if (q->count == q->length) {
if(!expand(q)) return 0;
printf("success to expand ! the size = %d\n", q->length);
};
q->data[q->tail++] = val;
if(q->tail == q->length) q->tail = 0;
q->count += 1;
return 1;
}
int pop(Queue *q) {
if (q == NULL) return 0;
if (empty(q)) return 0;
q->head += 1;
if(q->head == q->length) q->head = 0;
q->count -= 1;
return 1;
}
void clear(Queue *q) {
if (q == NULL) return ;
free(q->data);
free(q);
return ;
}
void output(Queue *q) {
printf("Queue: [");
for (int i = q->head, j = 0; i < q->tail, j < q->count; j++) {
j && printf(" ");
printf("%d", q->data[(i + j) % q->length]);
}
printf("]\n");
return ;
}
int main() {
srand(time(0));
#define MAX_OP 20
Queue *q = init(5);
for (int i = 0; i < MAX_OP; i++){
int op = rand() % 4;
int val = rand() % 100;
switch (op) {
case 0:
case 1:
case 2: {
printf("push %d to Queue = %d\n", val, push(q, val));
}break;
case 3: {
if (empty(q)) {
printf("fail to pop a item!\n");
} else {
printf("success to pop a item : %d\n", front(q));
pop(q);
}
}break;
}
output(q), printf("\n");
}
return 0;
}
链队列
#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_LinkQueue();
int push(Queue *, int);
int pop(Queue *);
void clear_node(Node *);
void clear(Queue *);
int empty(Queue *);
int front(Queue *);
Node *getNewNode(int val) {
Node *p = (Node *)malloc(sizeof(Node));
p->data = val;
p->next = NULL;
return p;
}
Queue *init_LinkQueue() {
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;
}
int front(Queue *q) {
return q->head.next->data;
}
int push(Queue *q, int val) {
if (q == NULL) return 0;
Node *node = getNewNode(val);
q->tail->next = node;
q->tail = node;
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);
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) {
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));
#define MAX_OP 20
Queue *q = init_LinkQueue();
for (int i = 0; i < MAX_OP; i++) {
int val = rand() % 100;
int op = rand() % 4;
switch(op) {
case 0:
case 1:
case 2: {
printf("push %d to Queue = %d\n", val, push(q,val));
output(q), printf("\n");
}break;
case 3: {
if(empty(q)) {
printf("fail to pop!\n");
}else{
printf("success to pop %d\n", front(q));
pop(q);
output(q), printf("\n");
}
}break;
}
}
#undef MAX_OP
clear(q);
return 0;
}