队列

队列

队列:先进先出 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值