数据结构队列(C语言版)

队列(Queue)是一种先进先出(First In First Out, FIFO)的线性数据结构。以下是关于队列的详细解释:

队列的基本概念

  1. 先进先出(FIFO):队列中的元素,最先被插入(enqueue)的,最先被取出(dequeue)。

  2. 队头与队尾:队列有两个端点,队头(front)和队尾(rear)。队头是元素被取出的位置,队尾是元素被插入的位置。

队列的物理实现

队列可以使用数组或链表来实现:

  • 数组实现:使用一个固定大小的数组来存储队列元素,并维护两个指针(或索引)分别指向队头和队尾。
  • 链表实现:使用链表节点来存储队列元素,每个节点包含数据和指向下一个节点的指针。队列使用两个指针分别指向链表的头节点和尾节点。

队列的基本操作

以下为队列的主要操作:

  1. 初始化(Init):创建一个空队列。
  2. 入队(Enqueue):在队尾插入一个新元素。
  3. 出队(Dequeue):移除队头的元素。
  4. 查看队头元素(Front):返回队头元素的值,但不移除它。
  5. 判断队列是否为空(IsEmpty):检查队列是否不包含任何元素。
  6. 判断队列是否满(IsFull):仅在固定大小的队列中需要,检查队列是否达到其容量限制。

队列的操作示例

以下是使用数组实现的队列的操作示例:

初始化
#define MAX_SIZE 100

typedef struct Queue {
    int data[MAX_SIZE];
    int front;
    int rear;
} Queue;

void initQueue(Queue *q) {
    q->front = 0;
    q->rear = 0;
}
入队
bool enqueue(Queue *q, int value) {
    if ((q->rear + 1) % MAX_SIZE == q->front) {
        // 队列满,无法入队
        return false;
    }
    q->data[q->rear] = value;
    q->rear = (q->rear + 1) % MAX_SIZE; // 环形队列的队尾指针移动
    return true;
}
出队
bool dequeue(Queue *q, int *value) {
    if (q->front == q->rear) {
        // 队列空,无法出队
        return false;
    }
    *value = q->data[q->front];
    q->front = (q->front + 1) % MAX_SIZE; // 环形队列的队头指针移动
    return true;
}
查看队头元素
bool front(Queue *q, int *value) {
    if (q->front == q->rear) {
        // 队列空,无法查看队头元素
        return false;
    }
    *value = q->data[q->front];
    return true;
}
判断队列是否为空
bool isEmpty(Queue *q) {
    return q->front == q->rear;
}
判断队列是否满
bool isFull(Queue *q) {
    return (q->rear + 1) % MAX_SIZE == q->front;
}

队列的应用

队列在计算机科学中有广泛的应用,以下是一些例子:

  • 任务调度:操作系统使用队列来管理任务和进程。
  • 缓冲处理:在网络中,队列用于缓冲数据包。
  • 广度优先搜索(BFS):在图论中,队列用于广度优先搜索算法。
  • 打印队列:打印任务通常在队列中等待,按照到达顺序进行处理。

队列的优缺点

优点

  • 插入和删除操作的时间复杂度为O(1),效率高。
  • 实现简单。

缺点

  • 固定大小的队列可能导致空间浪费或不足。
  • 链表实现的队列需要额外的内存来存储节点间的指针。

代码示例

循环队列
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef int data_t;
typedef struct seq // 循环队列结构体
{
    data_t data[N]; // 循环队列存储数据的数组
    int head;       // 队头元素下标
    int tail;       // 队尾元素下标
} seq_t, *seq_p;

// 创建空队列
seq_p create_sequeue()
{
    seq_p p = (seq_p)malloc(sizeof(seq_t)); // 开辟循环队列大小空间
    if (NULL == p)
    {
        perror("malloc err"); // perror打印上一个函数报的错误
        return NULL;          // 错误情况让函数返回空指针
    }
    // 对结构体初始化
    p->head = 0;
    p->tail = 0;
    return p;
}

// 判满
int full_qeuqeu(seq_p p)
{
    return (p->tail + 1) % N == p->head;
}

// 入队
void push_queue(seq_p p, int data)
{
    if (full_qeuqeu(p))
    {
        printf("full\n");
    }
    p->data[p->tail] = data;
    p->tail = (p->tail + 1) % N;
}

// 判空
int null_qeuqeu(seq_p p)
{
    return p->tail == p->head;
}

// 出队
int pop_queue(seq_p p)
{
    if (null_qeuqeu(p))
    {
        printf("null\n");
    }
    int i = p->head;
    while (i != p->tail)
    {
        printf("%d ", p->data[i]);
        i = (i + 1) % N;
    }
    printf("\n");
}

// 求长度
int len_queque(seq_p p)
{
    return (p->tail - p->head + N) % N;
}

int main(int argc, char const *argv[])
{
    seq_p p = create_sequeue();
    int i = 0, num;
    while (scanf("%d", &num) != EOF)
    {
        push_queue(p, num);
    }
    pop_queue(p);
    printf("len:%d\n", len_queque(p));
    return 0;
}
链式队列
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct node // 链式队列结构体
{
    data_t data;
    struct node *next;
} node_t, *node_p;

typedef struct linkqueue // 将队列的头尾指针封装成一个结构体
{
    node_p head; // 队列的头指针
    node_p tail; // 队列的尾指针
} linkqueue_t, *linkqueue_p;

// 创建一个空的队列,用有头链表
linkqueue_p create_linkqueue()
{
    // 开辟队列结构体大小空间
    linkqueue_p p = (linkqueue_p)malloc(sizeof(linkqueue_t));
    if (NULL == p)
    {
        perror("error");
        return NULL;
    }
    // 初始化队列结构体, 让头尾指针都指向开辟的头节点
    p->head = p->tail = (node_p)malloc(sizeof(node_t));
    if (NULL == p->head)
    {
        perror("p->front malloc err");
        return NULL;
    }
    // 初始化头节点
    p->head->next = NULL;
    return p;
}

// 入队
int push_linkqueue(linkqueue_p p, int data)
{
    // 新建节点,保存入队数据
    node_p new = (node_p)malloc(sizeof(node_t));
    if (NULL == new)
    {
        perror("new error");
        return -1;
    }
    new->data = data;    // 将数据插入新节点数据域
    new->next = NULL;    // 新节点指针域置空
    p->tail->next = new; // 将新节点尾插到链表
    p->tail = new;       // 移动尾指针到新节点   让新结点成为尾节点
    return 0;
}

// 出队
int pop_linkqueue(linkqueue_p p)
{
    if (p->head == p->tail)//判空
    {
        printf("null\n");
    }
    node_p del = NULL;
    while (p->head->next != NULL)
    {
        del = p->head;//定义del保存当前头节点
        // printf("%d ", del->data);
        p->head = del->next;//将头指针向后移动
        free(del);//释放pdel
        printf("%d ", p->head->data);//将要出队数据输出
    }
    printf("\n");
}

//计算长度
int len_linkqueue(linkqueue_p p)
{
    int len=0;
    node_p q=p->head->next;
    while(q != NULL)
    {
        len++;
        q=q->next;
    }
    return len;
}

int main(int argc, char const *argv[])
{
    linkqueue_p p = create_linkqueue();
    int num;
    while (scanf("%d", &num) != EOF)
    {
        push_linkqueue(p, num);
    }
    // node_p h = p->head;
    // while (h->next != NULL)
    // {
    //     h = h->next;
    //     printf("%d ", h->data);
    // }
    // printf("\n");
    printf("%d\n",len_linkqueue(p));
    pop_linkqueue(p);
    return 0;
}
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值