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日

相关文章

  • Halcon学习教程(一) 之提取十字线中心 图像分割

      原文作者:aircraft   原文链接:https://www.cnblogs.com/DOMLX/p/17266405.html      废话不多说,因为毕业后工作原因比较忙,好久没更新博客了,直接上图。。。     上图有个十字线,我们要提取出十字线的中心(Hhhh这个线是我随手画的 没画直!!) 第一步:肯定是读取图像进行灰度提取处理啦。   …

    算法与数据结构 2023年4月18日
    00
  • C语言实题讲解快速掌握单链表下

    C语言实题讲解快速掌握单链表下 简介 单链表是常见的一种数据结构,可以存储任意数量的数据,并且可以高效的进行插入、删除和查找操作。本篇文章将介绍如何使用C语言实现单链表,以及如何应对在实现单链表时所遇到的常见问题。 实现过程 数据结构设计 为了实现单链表,我们需要设计一个数据结构来存储节点信息,一般包含两个成员,一个是数据域,用来存储实际的数据,另一个是指针…

    数据结构 2023年5月17日
    00
  • Python实现的数据结构与算法之双端队列详解

    Python实现的数据结构与算法之双端队列详解 什么是双端队列? 双端队列是一种具有队列和栈的性质的数据结构,可以在队列两端进行插入和删除操作。双端队列可以实现两端的操作,因此可以在队列两端进行插入和删除操作,既可以像队列一样先进先出,也可以像栈一样后进先出。 双端队列的操作 add_front(item):在队头插入一个元素; add_rear(item)…

    数据结构 2023年5月17日
    00
  • el-tree的实现叶子节点单选的示例代码

    下面我将详细讲解“el-tree的实现叶子节点单选的示例代码”的完整攻略。 示例代码实现 el-tree 的实现叶子节点单选,需要在 el-tree 上绑定 @check-change 事件,并通过 check-strictly 属性来配置选择模式。代码示例如下: <template> <el-tree :data="data&q…

    数据结构 2023年5月17日
    00
  • 四边形不等式学习笔记

    简要题意 四边形不等式是一种 dp 优化策略。多用于 2D DP。 内容 对于区间 \([l,r]\) 带来的贡献 \(w(l,r)\),如果其满足: 对于 \(L\leq l\leq r \leq R\),\(w(L,r)+w(l,R)\leq w(L,R)+w(l,r)\) 则称 \(w\) 满足四边形不等式。特别地,如果上式符号取等,则称其满足四边形恒…

    算法与数据结构 2023年4月17日
    00
  • java实现队列数据结构代码详解

    Java实现队列数据结构代码详解 1. 队列数据结构简介 队列(Queue)是一种先进先出(FIFO)的数据结构,支持在一端插入元素,在另一端删除元素并返回删除的元素。其操作包括入队(enqueue)和出队(dequeue)。 2. 队列实现方法 队列可以通过数组或链表来实现。其中,数组实现的队列称为顺序队列,链表实现的队列称为链式队列。 2.1 顺序队列 …

    数据结构 2023年5月17日
    00
  • 剑指 Offer 33. 二叉搜索树的后序遍历序列(java解题)

    目录 1. 题目 2. 解题思路 3. 数据类型功能函数总结 4. java代码 5. 踩坑小记 递归调用,显示StackOverflowError 1. 题目 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树: 5 / \ 2 6 /…

    算法与数据结构 2023年4月23日
    00
  • C#数据结构揭秘一

    C#数据结构揭秘一攻略 C#数据结构是每个C#程序员必须熟练掌握的技能之一。本攻略将介绍常见的C#数据结构,包括数组、列表、栈、队列、散列表和字典。我们将会深入了解它们的特点、使用场景和使用方法,并附带代码示例加深理解。 数组 数组是存储单一类型元素的固定大小的集合结构。在C#中,可以使用以下方式声明和初始化一个数组: int[] nums1 = new i…

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