队列理解及实现(链表,附完整代码)

队列

什么是队列

【理解成我们平时的排队,先进先出,与先进后出的栈相反】

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(head)进行删除操作,而在表的后端(tail)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

对比

不同点

顺序表

链表

存储空间上

物理上连续

逻辑连续,物理不一定连续

随机访问

可以直接访问任意元素

必须从头结点开始寻找

任意位置插入或者删除元素

要搬移其他元素,效率低

只需更改结点的指针指向,效率高

插入

动态顺序表,空间不够需要扩容

没有容量概念,需要就申请,不用就释放

场景

元素高效存储,并且需要频繁访问

需要在任意位置插入或者删除频繁

由此表,以本人拙见,运用链表来实现更为方便,原因:

  1. 队列拥有多少元素不确定,链表可以做到需要就申请,不用就释放,更为方便
  2. 队列是先进先出,顺序固定,不需要随机访问

队列的实现:

  1. 定义结构体
//定义队列结构体

typedef struct Queue {

    int* data;

    int front;//队首

    int rear;//队尾

    int size;

}Queue;

  1. 队列的初始化

【让头尾都为空】

//初始化队列

Queue* initQueue(int size) {

    Queue* queue = (Queue*)malloc(sizeof(Queue));

    queue->data = (int*)malloc(size * sizeof(int));

    queue->front = queue->rear = -1; //初始时队列为空   

    queue->size = size;

    return queue;

}

  1. 判断队列是否为空

//判断是否为空队列

bool isEmpty(Queue* queue) {

    return queue->front == -1;// 队首指针为-1表示队列为空

}

  1. 判断队列是否为满
//判断队列是否满

bool isFull(Queue* queue) {

    return (queue->rear + 1) % queue->size == queue->front;  // 队列满时队尾指针的下一个位置是队首指针

}

  1. 入队

我们要开辟新的结点来存储数据

//入队

void enterQueue(Queue* queue, int value) {

    if (isFull(queue)) {

         printf("队列已满,无法入队。\n");

         return;

    }

    if (isEmpty(queue)) {

         queue->front = 0;//队首指针为0

    }

    queue->rear = (queue->rear + 1) % queue->size;//队尾指针循环增加

    queue->data[queue->rear] = value;

}

  1. 出队
//出队

int outQueue(Queue* queue) {

    if (isEmpty(queue)) {

         printf("队列为空,无法出队。\n");

         return -1;

    }

    int value = queue->data[queue->front];

    if (queue->front == queue->rear){

         queue->front = queue->rear = -1;//只有一个元素出队之后,队列为空

    }

    else

    {

         queue->front = (queue->front + 1) % queue->size;//队首指针循环增加

    }

   

    return value;

}

  1. 销毁队列

//销毁队列

void destroy(Queue* queue) {

    free(queue->data); // 释放队列元素数组内存

    free(queue); // 释放队列结构体内存

}

完整代码:

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>



// 定义队列结构体

typedef struct Queue {

    int* data;  // 存储队列元素的数组

    int front;  // 队首指针

    int rear;   // 队尾指针

    int capacity;  // 队列容量

} Queue;



// 初始化队列

Queue* initQueue(int capacity) {

    Queue* queue = (Queue*)malloc(sizeof(Queue));

    queue->data = (int*)malloc(capacity * sizeof(int));

    queue->front = queue->rear = -1;  // 初始时队列为空

    queue->capacity = capacity;

    return queue;

}



// 判断队列是否为空

bool isEmpty(Queue* queue) {

    return queue->front == -1;  // 队首指针为-1表示队列为空

}



// 判断队列是否已满

bool isFull(Queue* queue) {

    return (queue->rear + 1) % queue->capacity == queue->front;  // 队列满时队尾指针的下一个位置是队首指针

}



// 入队操作

void enqueue(Queue* queue, int value) {

    if (isFull(queue)) {

        printf("队列已满,无法入队。\n");

        return;

    }

    if (isEmpty(queue)) {

        queue->front = 0;  // 队列为空时设置队首指针为0

    }

    queue->rear = (queue->rear + 1) % queue->capacity;  // 队尾指针循环增加

    queue->data[queue->rear] = value;  // 入队操作

}



// 出队操作

int dequeue(Queue* queue) {

    if (isEmpty(queue)) {

        printf("队列为空,无法出队。\n");

        return -1;

    }

    int value = queue->data[queue->front];  // 获取队首元素

    if (queue->front == queue->rear) {

        queue->front = queue->rear = -1;  // 队列中只有一个元素时出队后队列为空

    }

    else {

        queue->front = (queue->front + 1) % queue->capacity;  // 队首指针循环增加

    }

    return value;

}



// 打印队列元素

void printQueue(Queue* queue) {

    if (isEmpty(queue)) {

        printf("队列为空,无法打印。\n");

        return;

    }

    printf("队列元素:");

    int index = queue->front;

    while (index != queue->rear) {

        printf("%d ", queue->data[index]);

        index = (index + 1) % queue->capacity;  // 循环遍历队列

    }

    printf("%d\n", queue->data[index]);  // 打印队尾元素

}



// 销毁队列

void destroyQueue(Queue* queue) {

    free(queue->data);  // 释放队列元素数组内存

    free(queue);  // 释放队列结构体内存

}



int main() {

    Queue* queue = initQueue(5);  // 初始化队列容量为5的队列



    enqueue(queue, 3);

    enqueue(queue, 9);

    enqueue(queue, 5);

    printQueue(queue);  // 打印队列元素:3 9 5



    printf("队首元素:%d\n", dequeue(queue));  // 出队并打印队首元素:3

    printQueue(queue);  // 打印队列元素:9 5



    printf("队首元素:%d\n", dequeue(queue));  // 出队并打印队首元素:9

    printf("队首元素:%d\n", dequeue(queue));  // 出队并打印队首元素:5

    printf("是否为空:%d\n", isEmpty(queue));  // 打印队列是否为空:1 (空队列为true)



    enqueue(queue, 7);

    enqueue(queue, 2);

    printQueue(queue);  // 打印队列元素:7 2



    printf("是否为满:%d\n", isFull(queue));  // 打印队列是否为满:0 (未满为false)



    destroyQueue(queue);  // 销毁队列

    return 0;

}

代码效果:

总结:

1. 队列的基本操作:入队、出队、判断队列是否为空 和 判断队列是否已满。

2. 队列的存储方式:可以使用数组(顺序表)或链表来存储队列中的元素。使用数组时,需要考虑队列的大小和元素的类型;使用链表时,需要考虑链表的节点类型和节点的插入和删除操作。【本文使用的是链表】

3. 队列的入队和出队操作:入队操作需要将元素添加到队尾,出队操作需要将队首的元素取出。在入队和出队操作中,需要考虑队列的边界情况,例如队列已满时无法入队,队列已空时无法出队。

4. 队列的效率:在实现队列时,需要考虑队列的效率。例如,使用数组实现队列时,需要考虑数组的扩容问题;使用链表实现队列时,需要考虑链表的查找和删除操作的时间复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值