【数据结构03】循环队列+链表队列

文章提供了两种实现队列的方式,一种是基于连续内存的数组(包括循环队列的实现),另一种是基于离散内存的链表。循环队列通常使用数组来实现,以优化内存使用。代码示例中展示了如何初始化、压入元素、弹出元素、检查队列是否为空以及如何在数组实现的循环队列中进行动态扩容。此外,还给出了链表实现的队列,包括节点的创建、队列的初始化和释放等操作。
摘要由CSDN通过智能技术生成

队列的代码实现方式有两种:一种实现方式是连续内存的数组,一种实现方式是离散内存的链表。

而循环队列一般采用连续内存的数组来实现。

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;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值