数据结构 链式队列

队列

定义

  • FIFO LILO

  • 先进先出,后进后出

  • 循环队列 顺序队列

  • 链式队列

比较循环队列和链式队列

项目循环队列链式队列
插入和删除时间复杂度O(1)o(1)
是否会满

链式队列实现

结构体定义

struct _QNode {
    struct _QNode *next;
    char elem[];
};

#define _QNODESIZE sizeof(struct _QNode)

struct Queue {
    size_t elemSize; // 存储元素类型字节数
    size_t size;
    struct _QNode *head; // 指向队列首
    struct _QNode *tail; // 指向队列尾
};

typedef struct Queue* QE;

基础函数声明

// 创建空队列
QE create_queue(size_t elemSize);

// 销毁队列
void destroy_queue(QE q);

// 清空队列
void clear_queue(QE q);

// 队列中元素个数
size_t size_queue(QE q);

// 判断队列是否为空
bool empty_queue(QE q);

// 压入队尾
int push_queue(QE q, const void *pElem);

// 从队头弹出
int pop_queue(QE q, void *pElem);

// 获取队头元素
int front_queue(QE q, void *pElem);

// 获取队尾元素
int back_queue(QE q, void *pElem);

//迭代
void foreach_queue(QE q, void (*foreach)(const void*));

基础函数实现

创建空队列 create_queue
QE create_queue(size_t elemSize)
{
    QE q = (QE)malloc(sizeof(struct Queue)); // 创建空队列
    if (q != NULL) {
        q->elemSize = elemSize; // 元素字节大小
        q->size = 0;
        q->head = NULL; // 没有元素指向空
        q->tail = NULL; // 没有元素指向空
    }
    return q;
}
销毁队列 destroy_queue
void destroy_queue(QE q)
{
    assert(q != NULL);
    clear_queue(q);
    free(q);
}
清空队列 clear_queue
void clear_queue(QE q)
{
    assert(q != NULL);
    while (!empty_queue(q)) {
        pop_queue(q, NULL);
    }
    
    /*
    // 用for循环一个一个释放
    struct _QNode *node, *next;
    for (node = q->head; node != NULL; node = next) {
        next = node->next;
        free(node);
    }
    q->head = NULL;
    q->tail = NULL;
    q->size = 0;
    */
}
队列中元素个数 size_queue
size_t size_queue(QE q)
{
    assert(q != NULL);
    return q->size;
}
判断队列是否为空 empty_queue
bool empty_queue(QE q)
{
    assert(q != NULL);
    return q->size == 0; // q->head == NULL;
}
压入队尾 push_queue
int push_queue(QE q, const void *pElem)
{
    assert(q != NULL && pElem != NULL);
    struct _QNode *node = (struct _QNode*)malloc(_QNODESIZE + q->elemSize); // 结点大小+元素大小
    if (node == NULL) {
        return FAILURE;
    }
    node->next = NULL;
    memcpy(node->elem, pElem, q->elemSize); // 拷贝元素
    if (q->tail != NULL) {
        q->tail->next = node; // 让node结点放到原来队尾结点的后面
    } else { // 如果没有结点 那么node也得第一个结点
        q->head = node; // 第一次压入
    }
    q->tail = node; // 队尾指针指向刚压入的元素结点
    ++q->size;
    return SUCCESS;
}
从队头弹出 pop_queue
int pop_queue(QE q, void *pElem)
{
    assert(q != NULL);
    if (empty_queue(q)) {
        return FAILURE;
    }
    struct _QNode *node = q->head;
    if (pElem != NULL) { // 是否返回删除的元素
        memcpy(pElem, node->elem, q->elemSize);
    }
    q->head = node->next;
    if (node == q->tail) { // 只有一个结点 删除之后 head和tail都要为NULL
        q->tail = NULL;
    }
    free(node);
    --q->size;
    return SUCCESS;
}
获取队头元素 front_queue
int front_queue(QE q, void *pElem)
{
    assert(q != NULL && pElem != NULL);
    if (empty_queue(q)) {
        return FAILURE;
    }
    memcpy(pElem, q->head->elem, q->elemSize);
    return SUCCESS;
}
获取队尾元素 back_queue
int back_queue(QE q, void *pElem)
{
    assert(q != NULL && pElem != NULL);
    if (empty_queue(q)) {
        return FAILURE;
    }
    memcpy(pElem, q->tail->elem, q->elemSize);
    return SUCCESS;
}
迭代 foreach_queue
void foreach_queue(QE q, void (*foreach)(const void*))
{
    assert(q != NULL && foreach != NULL);
    struct _QNode *node;
    for (node = q->head; node != NULL; node = node->next) {
        foreach(node->elem);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值