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日

相关文章

  • 比特币区块链的数据结构

    让我来为你详细讲解比特币区块链的数据结构。 1. 区块链的定义 比特币区块链是一个去中心化的、可追溯的、公共的、可验证的交易数据库。每一笔交易都通过哈希算法,与之前的交易连接成一个区块,形成了一个数据结构链,也就是“区块链”。 2. 区块链的数据结构 区块链的数据结构由区块、交易和哈希三部分组成: 区块 区块是区块链数据结构的基本单位,每一个区块代表着一段时…

    数据结构 2023年5月17日
    00
  • 【ACM算法竞赛日常训练】DAY5题解与分析【储物点的距离】【糖糖别胡说,我真的不是签到题目】| 前缀和 | 思维

    DAY5共2题: 储物点的距离(前缀和) 糖糖别胡说,我真的不是签到题目(multiset,思维) ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?? 原文链接(阅读原文获得更好阅读体验):https://www.eri…

    算法与数据结构 2023年4月18日
    00
  • C语言深入浅出讲解顺序表的实现

    C语言深入浅出讲解顺序表的实现 顺序表简介 顺序表是一种线性表的存储结构,它是由连续的内存空间来存储线性表中的元素。 顺序表的特点是支持查找、插入和删除操作,操作效率较高,但需要提前分配足够大的内存空间。当顺序表空间不足时,需要扩容,移动数据较为麻烦。 顺序表的实现 数据结构定义 顺序表的数据结构定义包含以下几个成员: 数据元素数组 data,存储线性表中的…

    数据结构 2023年5月17日
    00
  • InputStream数据结构示例解析

    InputStream数据结构示例解析 InputStream是Java中一个重要的数据结构,它表示可以从其中读取数据的输入流。通常情况下,它表示的是用来读取字节流数据的输入流。在本篇攻略中,我们将会详细解释如何使用InputStream数据结构来读取字节流数据,并且给出两条具体的读取示例。 InputStream类的继承结构 InputStream类是一个…

    数据结构 2023年5月17日
    00
  • C语言数据结构实现银行模拟

    C语言数据结构实现银行模拟攻略 背景介绍 银行模拟是计算机学科中一个重要的数据结构实践练习项目。它涉及到队列(Queue)等数据结构的应用,也是计算机基础课程的一个重要组成部分。 代码实现 1. 队列的实现 首先,我们需要实现一个队列(Queue)结构体,包含 QueueSize、Front、Rear 三个成员变量: struct Queue { int Q…

    数据结构 2023年5月17日
    00
  • C#数据结构与算法揭秘二 线性结构

    C#数据结构与算法揭秘二 线性结构 线性结构是指数据元素之间一对一的关系,即数据元素之间存在一个前驱和一个后继。一般有两种基本形式:线性表和栈、队列。 线性表 线性表是由同类型数据元素构成有序序列的线性结构,常被用于实现基于数组的数据结构,如向量、矩阵等。 线性表可以分为顺序表和链表两种。 顺序表(Sequence List):是把线性表的元素按照顺序存储在…

    数据结构 2023年5月17日
    00
  • 用C语言举例讲解数据结构中的算法复杂度结与顺序表

    让我来为你讲解“用C语言举例讲解数据结构中的算法复杂度结与顺序表”的完整攻略。具体如下: 一、算法复杂度 1.1 什么是算法复杂度 算法复杂度是衡量算法运行效率的重要指标。包括时间复杂度和空间复杂度。时间复杂度指算法解决问题所用的时间,通常用大O符号表示;空间复杂度指算法解决问题所需的内存空间大小。 1.2 如何分析算法复杂度 可以从以下三个方面来分析算法复…

    数据结构 2023年5月17日
    00
  • 稀疏数组

    引入 当在网页上下棋类游戏时,玩到中途想要离开,但是我们需要保存进度,方便下次继续 我们应该怎么实现 ? 以围棋举例 使用二维数组将棋盘记下 ,如 0 为 没有棋子 ,1 为 黑子 , 2为白子 但是没有棋子的地方都为 0 ,整个二维数组充斥着大量的无效数据 0 我们需要想一个办法来 优化存储的方式 基本介绍 当一个数组中大部分元素是同一个值时,我们可以使用…

    算法与数据结构 2023年4月19日
    00
合作推广
合作推广
分享本页
返回顶部