C语言数据结构系列队列篇

C语言数据结构系列队列篇攻略

简介

队列(Queue)是一种先进先出(First In First Out, FIFO)的线性数据结构,类似于排队买票的过程。本篇攻略将带您从以下三个方面深入浅出地了解C语言数据结构系列队列篇:

  • 队列的特点;
  • 队列的实现;
  • 队列的应用。

队列的特点

队列有两个特殊的端点,队头(front)和队尾(rear)。队头指示队列的头部元素,队尾指示队列的尾部元素。当元素进入队列时,其被添加到队列的末尾处;当元素离开队列时,其从队列的前端删除。下面是队列的几个特点:

  • 插入(Insert)操作在队尾进行;
  • 删除(Delete)操作在队头进行;
  • 队列只允许在一端进行插入操作,在另一端进行删除操作;
  • 队列先进先出,即先插入队列的元素先删除;
  • 具有一定的局限性,一般只能从队列头或尾访问元素。

队列的实现

顺序队列

Queue是一种先进先出(FIFO)的数据结构。最简单的实现队列的方式是使用顺序结构,如数组。数组的优点是简单易实现,缺点是当队列元素进行删除操作后,其余元素位置会向前移一位并占用原来的位置,这会造成空间的浪费。下面是顺序队列的示意代码:

#define MAXQUEUE 10 // 队列的最大元素个数
typedef struct{
    int data[MAXQUEUE];
    int rear,front;
    int size; // 队列中实际元素个数
}Queue;

void initQueue(Queue *q){
    q->rear = -1;
    q->front = -1;
    q->size = 0;
}

// 判断队列是否为空
bool isEmpty(Queue *q){
    return (q->size == 0);
}

// 判断队列是否已满
bool isFull(Queue *q){
    return (q->size == MAXQUEUE);
}

// 入队操作(在队尾插入元素)
bool enqueue(Queue *q, int x){
    if (isFull(q)){
        printf("Error:队列已满,插入失败!");
        return false;
    }else{
        q->rear++;
        q->data[q->rear] = x;
        q->size++;
        return true;
    }
}

// 出队操作(在队头删除元素)
bool dequeue(Queue *q, int *x){
    if (isEmpty(q)){
        printf("Error:队列已空,删除失败!");
        return false;
    }else{
        q->front++;
        *x = q->data[q->front];
        q->size--;
        return true;
    }
}

// 获取队头元素
bool getHead(Queue *q, int *x){
    if (isEmpty(q)){
        printf("Error:队列已空!");
        return false;
    }else{
        *x = q->data[q->front+1];
        return true;
    }
}

链式队列

链表是另一种实现队列的方式,链表就是将结点放在任意的内存位置上,通过指针相互连接。链表的优点是没有浪费空间,缺点是需要动态地分配和释放内存存储队列元素。链表也是一种重要的数据结构,下面是链式队列的示意代码:

typedef struct node{
    int data;
    struct node *next;
}Node;

typedef struct {
    Node *front;
    Node *rear;
}Queue;

void initQueue(Queue *q){
    q->front = q->rear = NULL;
}

// 判断队列是否为空
bool isEmpty(Queue *q){
    return (q->front == NULL);
}

// 入队操作(在队尾插入元素)
void enqueue(Queue *q, int x){
    Node *s = (Node*)malloc(sizeof(Node));
    s->data = x;
    s->next = NULL;
    if (q->rear == NULL){
        q->front = q->rear = s;
    }else{
        q->rear->next = s;
        q->rear = s;
    }
}

// 出队操作(在队头删除元素)
int dequeue(Queue *q){
    int x;
    Node *p;
    if (q->front == NULL){
        printf("Error:队列为空!");
        return false;
    }
    x = q->front->data;
    p = q->front;
    q->front = q->front->next;
    if (q->front == NULL) q->rear = NULL;
    free(p);
    return x;
}

// 获取队头元素
int getHead(Queue *q){
    if (q->front == NULL){
        printf("Error:队列为空!");
        exit(1);
    }
    return q->front->data;
}

队列的应用

BFS广度优先算法

BFS(Breadth-First-Search)也叫广度优先搜索,最短路径是一个重要的应用。BFS算法的核心是从起点开始不断地将其周围的节点加入队列,然后每次从队列首部取出一个节点,如果这个节点是终点,则搜索成功结束;否则继续将该节点周围的节点加入队列,如此往复,直至队列为空或找到终点。下面是BFS算法的示例代码:

#define MAXN 100 // 图的最大节点数
#define INF 0x3f3f3f // 无穷大
int n, e[MAXN][MAXN], dis[MAXN]; // n 为节点数,e 为图的临界矩阵,dis 为起点到其它节点的距离

// BFS广搜模板
void BFS(int s){
    Queue q;
    bool vis[MAXN] = {false}; // 访问标记
    initQueue(&q);
    enqueue(&q, s); // 起点入队
    vis[s] = true; // 标记起点已访问
    while (!isEmpty(&q)){
        int v = dequeue(&q); // 队首元素出队
        for (int i = 0; i < n; i++){
            if (e[v][i] != INF && !vis[i]){ // 如果v和i之间有边并且i未访问过
                dis[i] = dis[v] + 1; // 计算起点到i的距离
                vis[i] = true; // 标记节点i已访问过
                enqueue(&q, i); // 节点i入队
            }
        }
    }
}

循环队列

循环队列是一种环形队列,队尾指针总是在队头指针的左边。当队列头尾相连时,队列到达数组的末尾后就从数组的头重新开始。下面是循环队列的示例代码:

typedef struct{
    int data[MAXQUEUE];
    int front, rear; // 队头和队尾指针
    int size; // 队列中实际元素个数
}Queue;

// 判断队列是否为空
bool isEmpty(Queue *q){
    return (q->front == q->rear);
}

// 判断队列是否已满
bool isFull(Queue *q){
    return (q->rear+1) % MAXQUEUE == q->front;
}

// 入队操作(在队尾插入元素)
bool enqueue(Queue *q, int x){
    if (isFull(q)){
        printf("Error:队列已满,插入失败!");
        return false;
    }else{
        q->rear = (q->rear + 1) % MAXQUEUE;
        q->data[q->rear] = x;
        q->size++;
        return true;
    }
}

// 出队操作(在队头删除元素)
bool dequeue(Queue *q, int *x){
    if (isEmpty(q)){
        printf("Error:队列已空,删除失败!");
        return false;
    }else{
        q->front = (q->front + 1) % MAXQUEUE;
        *x = q->data[q->front];
        q->size--;
        return true;
    }
}

// 获取队头元素
bool getHead(Queue *q, int *x){
    if (isEmpty(q)){
        printf("Error:队列已空!");
        return false;
    }else{
        *x = q->data[(q->front + 1) % MAXQUEUE];
        return true;
    }
}

总结

本篇攻略介绍了队列的特点、实现方法和应用。C语言是很实用的一门编程语言,队列是C语言数据结构中重要的一部分。队列可以理解为排队的过程,插入操作在队尾进行,删除操作在队头进行,先进先出。我们可以用数组或链表实现队列,数组简单易懂,链表存储元素无需按顺序排列。如果不想浪费内存,我们可以使用链式队列,如果空间耗用率不是太高,可以使用顺序队列。在算法实现中,BFS广度优先搜索用于解决最短路径等问题,循环队列可以优化队列的操作,提高效率。理解队列的特点、实现方法和应用,有助于提高编程技巧和程序设计水平。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构系列队列篇 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C++20中的结构化绑定类型示例详解

    ” C++20中的结构化绑定类型示例详解 ” 具体攻略如下: 什么是结构化绑定类型? 结构化绑定类型是C++17中的新特性,它可以让我们将一个复杂类型的元素绑定到某个变量上,从而更方便地使用这些元素。 C++20还进一步扩展了结构化绑定类型的功能,可以通过给用于引用的名字声明类型来进行显式类型的绑定。 结构化绑定类型的基本用法 下面的例子展示了如何使用结构化…

    数据结构 2023年5月17日
    00
  • C语言数据结构之动态分配实现串

    C语言数据结构之动态分配实现串 序言 在本文中,我们将探讨C语言中动态分配实现串的方法和技巧。本文将会从什么是动态分配串开始,详细介绍如何实现动态分配串,并给出一些示例代码帮助读者更好地理解。 什么是动态分配串 一个串(string)是由零个或多个字符组成的有限序列。串的实现可以分为两种形式:静态分配和动态分配。动态分配串是指在运行时动态地分配内存,以适应不…

    数据结构 2023年5月17日
    00
  • JavaScript 数据结构之散列表的创建(2)

    下面是详细讲解“JavaScript 数据结构之散列表的创建(2)”的完整攻略。 散列表(哈希表) 散列表是一种数据结构,使用哈希函数将键映射到索引。散列表可以在常量时间 O(1) 中进行插入、删除和查找操作,但也具有碰撞冲突问题。 碰撞冲突问题 在散列表中,当两个不同的键通过哈希函数映射到了同一个索引位置时,就会发生碰撞冲突问题。解决碰撞冲突问题的方法有很…

    数据结构 2023年5月17日
    00
  • 栈(Stack)

    概述 栈就是一种 只允许在表尾进行插入和删除操作 的 线性表 栈的特点 先进后出 ,在表尾进行插入和删除操作 数组实现栈 crown crown:使用bottom来确定栈顶所在数组的下标,默认为 -1 空栈 当空栈时 ,crown = -1 栈是否为空 当 crown = -1 时 ,栈为空 ,不能 遍历 ,出栈 , 获取栈顶元素 栈是否已满 当 crown…

    算法与数据结构 2023年4月19日
    00
  • Python数据结构之链表详解

    Python数据结构之链表详解 链表简介 链表是一种数据结构,其每个节点都包含一个指向下一个节点的指针。链表可以用来表示序列,集合或映射等数据结构。在Python中,链表通常由节点和链表类来实现。 单向链表 单向链表是一种链表,每个节点包含指向下一个节点的指针。在Python中,一个节点可以由一个简单的对象表示,而整个链表必须由相互链接的节点组成。 下面是一…

    数据结构 2023年5月17日
    00
  • 滑动窗口总结

    前言 滑动窗口是双指针的一种特例,可以称为左右指针,在任意时刻,只有一个指针运动,而另一个保持静止。滑动窗口路一般用于解决特定的序列中符合条件的连续的子序列的问题。 好处:时间复杂度 O(n^2) —> O(n) 一、算法应用场景 关键词: 1.满足XXX条件(计算结果、出现次数、同时包含) 2.最长/最短/或最值 3.子串/子数组/子序列 最最最…

    算法与数据结构 2023年4月17日
    00
  • Python 数据结构之旋转链表

    Python 数据结构之旋转链表 简介 在进行链表操作时,有时需要旋转链表的一部分,即将链表的最后几个节点移到链表的头部。本文将讲解 Python 实现旋转链表的方法。 方法 我们需要了解两个概念:旋转链表、链表反转。 旋转链表 假设链表为1-2-3-4-5,k=2,将链表后两个节点移动到链表头部,即转化为4-5-1-2-3。 做法如下: 先遍历链表,得出链…

    数据结构 2023年5月17日
    00
  • Java数据结构之线性表

    Java数据结构之线性表完整攻略 什么是线性表 线性表是n个数据元素的有限序列,其中数据元素的类型相同。线性表中含有首元素和末元素。若表中只有一个数据元素,则该数据元素既是首元素又是末元素,这个数据元素成为线性表的唯一元素。 线性表的基本操作 初始化操作 initList(List L):建立一个空的线性表L 插入操作 insert(List L, int …

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部