C语言用链表(LinkedList)实现队列数据结构

本文详细介绍了如何使用链表结构体实现队列,包括初始化、入队(enqueue)和出队(dequeue)操作,以及内存管理。通过链表方式处理队列的优势在于内存扩展性和出队操作的便利性。
摘要由CSDN通过智能技术生成

简介

上篇文章介绍了如何用数组实现Queue队列,本篇文章将简单介绍一下使用链表实现队列数据结构。同样和链表实现堆栈一样,因为使用的单向链表所以队列的Front指针只能指向链表头部的位置,而对于只需要添加操作的Rear指针可以使用链表尾部的位置。

因为实现步骤都差不多,一些要点也写在代码注释里面了所以这篇文章就不具体介绍思路了直接贴代码

代码实现

linked_list_queue.h头文件

#ifndef C_LINKED_LIST_QUEUE_H
#define C_LINKED_LIST_QUEUE_H

typedef struct QueueNode *NodePtr;

// 这里需要一个指向结构体的指针,所以需要具名结构
// 不然不好定义上面的结构体指针别名NodePtr
typedef struct QueueNode {
    int data;
    NodePtr next;
} QNode;

// 可以使用匿名结构,也就是不要LinkedListQueue这个结构体名称
typedef struct LinkedListQueue {
    NodePtr front;
    NodePtr rear;
} LLQueue, *LLQueuePtr;

void initLinkedListQueue(LLQueuePtr queue);

void linkedListEnqueue(LLQueuePtr queue, int item);

int linkedListDequeue(LLQueuePtr queue);

void linkedListQueueTest(void);

#endif //C_LINKED_LIST_QUEUE_H

linked_list_queue.c代码文件

#include "linked_list_queue.h"
#include <stdio.h>
#include <stdlib.h>

void initLinkedListQueue(LLQueuePtr queue) {
    queue->front = NULL;
    queue->rear = NULL;
}

void linkedListEnqueue(LLQueuePtr queue, int item) {
    // 为结点申请内存空间
    NodePtr p = (NodePtr) malloc(sizeof(QNode));
    if (NULL == p) {
        printf("内存空间申请失败!!!\n");
    } else {
        // 当什么都没做初始化的队列新入列一个元素时,设置头尾指针都指向第一个元素
        if (queue->front == NULL) {
            queue->front = p;
        }
        if (queue->rear == NULL) {
            queue->rear = p;
        } else {
            // 如果此时Rear已经指向一个结点,那么需要将当前结点的Next指向新入列的结点p
            queue->rear->next = p;
            queue->rear = p;
        }
        p->data = item;
        // 新入列的结点Next指向NULL
        p->next = NULL;
    }
}

int linkedListDequeue(LLQueuePtr queue) {
    int ret = NULL;
    if (NULL == queue->front) {
        printf("this queue is empty\n");
    } else {
        // 前后都指向同一个位置说明此时队列里只剩下一个元素了
        ret = queue->front->data;
        NodePtr ptr = queue->front;
        // 链表头将要被删除,此时队列Front指向下一个队列元素结点
        queue->front = queue->front->next;
        // 将上一个元素结点内存回收
        free(ptr);
        // 有一种情况需要移动Rear,那就是本次出列后队列为空的时候
        if (NULL == queue->front) {
            queue->rear = NULL;
        }
    }

    return ret;
}

void linkedListQueueTest() {
    LLQueue llQueue;
    LLQueuePtr queue = &llQueue;
    initLinkedListQueue(queue);
    const int Size = 10;

    printf("start enqueue: \n");
    for (int i = 0; i < Size; ++i) {
        int num = rand() % 101;
        printf("this enqueue num is %d\n", num);
        linkedListEnqueue(queue, num);
    }

    printf("start dequeue: \n");
    for (int i = 0; i < Size; ++i) {
        printf("this dequeue num is %d\n", linkedListDequeue(queue));
    }
}

测试函数运行截图

测试函数运行截图

总结

用链表来处理队列真的很方便,也处理堆栈一样只要内存空间足够多就可以一直插入队列。同时出列操作也比用数组存储来的方便。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值