一个60行的C语言FIFO队列的demo

前言

因为需求只需要实现出队和入队操作,不必实现访问操作。只需要实现 PopPush 就行。

FIFO代码

#include <stdio.h>      // printf
#include <stdint.h>     // size_t
#include <malloc.h>     // malloc

typedef struct _MyList {
    void *_item;        // must be malloced
    struct _MyList *_next;
} MyList;

// 禁止改变容量 capa
typedef struct _MyQueue {
    MyList *_head;       // 头指针
    MyList *_tail;       // 尾指针
    size_t  _size;       // 已用空间
    size_t  _capa;       // 最大容量
} MyQueue;

MyQueue* MyQueueInit(size_t capa) {
    // calloc 会把空间置零, 故指针为 NULL
    MyQueue *queue = (MyQueue *) calloc(4, sizeof(void *));

    queue->_capa = capa;
    return queue;
}

void* MyQueuePopFront(MyQueue *_this) {
    if (_this->_size == 0)
        return NULL;
    
    -- _this->_size;
    MyList *tmp_head = _this->_head;
    void *ret_val = _this->_head->_item;
    _this->_head = _this->_head->_next;
    free(tmp_head);
    return ret_val;
}

// 入队 item, 如果满了,队首元素出队
void* MyQueuePushBack(MyQueue *_this, void *item) {
    // calloc 会把空间置零, 故 new_node->_next == NULL
    MyList *new_node = calloc(2, sizeof(void *));
    if (new_node == NULL) {
        printf("[CRIT WARN]: bad malloc in MyQueuePushBack!\n");
        return NULL;
    }
    new_node->_item = item;

    // 如果 size == 0, 则 head == tail == NULL
    if (_this->_size == 0)
        _this->_head = new_node;
    else
        _this->_tail->_next = new_node;
    
    _this->_tail = new_node;
    ++ _this->_size;

    // 如果满了, 就要出队
    if (_this->_size > _this->_capa)
        return MyQueuePopFront(_this);
    else
        return NULL;
}

注意事项

建议不要动 _capa 成员,理论上可以增大, 但不要减小到比 size 小。

含测试代码的完整代码

#include <stdio.h>      // printf
#include <stdint.h>     // size_t
#include <malloc.h>     // malloc

typedef struct _MyList {
    void *_item;        // must be malloced
    struct _MyList *_next;
} MyList;

// 禁止改变容量 capa
typedef struct _MyQueue {
    MyList *_head;       // 头指针
    MyList *_tail;       // 尾指针
    size_t  _size;       // 已用空间
    size_t  _capa;       // 最大容量
} MyQueue;

MyQueue* MyQueueInit(size_t capa) {
    // calloc 会把空间置零, 故指针为 NULL
    MyQueue *queue = (MyQueue *) calloc(4, sizeof(void *));

    queue->_capa = capa;
    return queue;
}

void* MyQueuePopFront(MyQueue *_this) {
    if (_this->_size == 0)
        return NULL;
    
    -- _this->_size;
    MyList *tmp_head = _this->_head;
    void *ret_val = _this->_head->_item;
    _this->_head = _this->_head->_next;
    free(tmp_head);
    return ret_val;
}

// 入队 item, 如果满了,队首元素出队
void* MyQueuePushBack(MyQueue *_this, void *item) {
    // calloc 会把空间置零, 故 new_node->_next == NULL
    MyList *new_node = calloc(2, sizeof(void *));
    if (new_node == NULL) {
        printf("[CRIT WARN]: bad malloc in MyQueuePushBack!\n");
        return NULL;
    }
    new_node->_item = item;

    // 如果 size == 0, 则 head == tail == NULL
    if (_this->_size == 0)
        _this->_head = new_node;
    else
        _this->_tail->_next = new_node;
    
    _this->_tail = new_node;
    ++ _this->_size;

    // 如果满了, 就要出队
    if (_this->_size > _this->_capa)
        return MyQueuePopFront(_this);
    else
        return NULL;
}

// 打印输出
typedef void (*PrintFun)(void *);

void MyQueuePrintAll(MyQueue *_this, PrintFun print_fun) {
    printf("(size = %d): [", _this->_size); 
    MyList *tmp_head = _this->_head;
    while (tmp_head != NULL) {
        print_fun(tmp_head->_item);
        printf(", ");
        tmp_head = tmp_head->_next;
    }
    printf("]\n");
}

// --------------------- 测试代码 --------------------- //

void TestPrintInt(void *item) {
    if (item == NULL)
        printf("NULL");
    else
        printf("%d", *(int *)item);
}

void TestPrintRetVal(void *item) {
    printf("ret_val = ");
    TestPrintInt(item);
    printf("\n");
}

void* TestNewInt(int num) {
    int *item = (int *)malloc(sizeof(int));
    *item = num;
}

int main() {
    // 1. 创建一个容量为4的队列
    MyQueue *queue = MyQueueInit(4);
    MyQueuePrintAll(queue, TestPrintInt);
    int *ret_val;
    // 2. push 一个 1
    ret_val = MyQueuePushBack(queue, TestNewInt(1));
    TestPrintRetVal(ret_val);
    MyQueuePrintAll(queue, TestPrintInt);
    // 3. push 2, 3
    ret_val = MyQueuePushBack(queue, TestNewInt(2));
    TestPrintRetVal(ret_val);
    ret_val = MyQueuePushBack(queue, TestNewInt(3));
    TestPrintRetVal(ret_val);
    MyQueuePrintAll(queue, TestPrintInt);
    // 4. pop
    ret_val = MyQueuePopFront(queue);
    TestPrintRetVal(ret_val);
    MyQueuePrintAll(queue, TestPrintInt);
    // 5. push 一个 4
    ret_val = MyQueuePushBack(queue, TestNewInt(4));
    TestPrintRetVal(ret_val);
    MyQueuePrintAll(queue, TestPrintInt);
    // 6. push 一个 5
    ret_val = MyQueuePushBack(queue, TestNewInt(5));
    TestPrintRetVal(ret_val);
    MyQueuePrintAll(queue, TestPrintInt);
    // 7. push 一个 6
    ret_val = MyQueuePushBack(queue, TestNewInt(6));
    TestPrintRetVal(ret_val);
    MyQueuePrintAll(queue, TestPrintInt);
    // 8. push 一个 7
    ret_val = MyQueuePushBack(queue, TestNewInt(7));
    TestPrintRetVal(ret_val);
    MyQueuePrintAll(queue, TestPrintInt);
    // 9. pop
    ret_val = MyQueuePopFront(queue);
    TestPrintRetVal(ret_val);
    MyQueuePrintAll(queue, TestPrintInt);
}

测试结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值