C利用语言实现数据结构之队列

 更新时间:2021年10月08日 09:04:10   作者:柳兮  
队列 (Queue):简称队,是另一种限定性的线性表,它只允许在表的一端插入元素,而在另一端删除元素。q=(a1, a2, a3, … an),其中a1为队头,an为队尾,下面文章小编将为大家详细介绍,需要的下伙伴可以参考一下

前言:

队列在生活中也比较常见,例如购物排队——新来的成员总是加入队尾,每次离开的成员总是队列头上的。

队列按存储方式可以分为两种:顺序队列和链队列。

一、链队列

链式队列中每个元素定义成一个结点,含数据域与指针域(指向下一结点),并设头尾指针。用图表示就是。

二、链队的表示

前面的链式结构,总是使用一个结点的结构来表示链表,但是在这里使用新的存储结构。定义一个结点结构,和一个队列结构。两个结构嵌套。

//定义节点结构
typedef struct QNode
{
    QElemType   data;   /*数据域*/
    struct QNode   * next;   /*指针域*/
 }QNode, *QueuePtr;
//定义队列结构
 typedef struct
 {
    QueuePtr front;
    QueuePtr rear;
 }LinkQueue;

三、链队的基本操作

1. 链队的初始化

Status initQueue(LinkQueue *Q)
{ 
    Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
    if(!Q.front) exit(OVERFLOW);
    Q.front->next = NULL;
    return OK;
}

2. 链队的销毁

Status destroyQueue(LinkQueue *Q)
{
    while (Q.front)
    {
        Q.rear = Q.front->next;
        free(Q.front);
        Q.front = Q.rear;
    }
   return OK;
}

3. 入队

Status enQueue(LinkQueue *Q, QElemType e)
{
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(!p) exit(OVERFLOW);
    //插入数据
    p->data = e;
    p->next = NULL;
    //Q.rear一直指向队尾
    Q.rear->next = p;
    Q.rear = p;
    return OK;
 }

4. 出队

Status deQueue(LinkQueue *Q, QElemType e)
{
    if(Q.front == Q.rear) return ERROR;
    QueuePtr p = Q.front->next;
    e = p->data;
    Q.front->next = p->next;   //队头元素p出队
    if(Q.rear == p)   //如果队中只有一个元素p, 则p出队后成为空队
    Q.rear = Q.front;     //给队尾指针赋值
    free(p);   //释放存储空间
    return OK;
}

四、顺序队列

用一组连续的存储单元依次存放队列的元素,并设两个指针frontrear分别指示队头和队尾元素的位置。
front:指向实际的队头;rear:指向实际队尾的下一位置。
初态front=rear=0;队空:front=rear;队满:rear=M;
入队q[rear]=x; rear= rear+1; 出队:x=q[front];front=front+1;

顺序队列的表示:

#define MAXQSIZE  100
typedef struct
{
    QElemType *base;
    int  front;   //头指针指示器 
    int  rear;  //尾指针指示器
} SqQueue;

存在的问题:

随着入队、出队操作的进行,整个队列会整体向后移动,这样就出现了下图的现象:队尾指针虽然已经移到了最后,而队列却未真满的“假溢出”现象,使得队列的空间没有得到有效的利用

那我们该如何解决假溢出的问题呢?

有以下两种方法:

  • 将队中元素向队头移动:当移动数据较多时将会影响队列的操作速度。
  • 采用循环队列:Q[0]接在Q[MAXQSIZE-1]之后,一个更有效的方法是将队列的数据区Q[0 .. MAXQSIZE-1]看成是首尾相连的环,即将表示队首的元素Q[0]与表示队尾的元素Q[MAXQSIZE–1]连接起来,形成一个环形表,这就成了循环队列。当Q.rear=MAXQSIZE-1时再入队,令Q.rear=0, 则可以利用已被删除的元素空间。如下图。

五、循环队列

在循环队列中,不可以根据等式front == rear可以判别队满和队空。因为此时条件是相同的,解决这种问题的方法一般有两种。

少用(损失)一个空间,以尾指针加1等于头指针作为队满的标志。因此:当front==rear,表示循环队列为空;当front ==(rear+1)% MAXLEN,表示循环队列为满。
在定义结构体时,附设一个存储循环队列中元素个数的变量n,当n==0时表示队空;当n==MAXLEN时为队满。

循环队列的基本操作:

1. 初始化

Status initQueue (SqQueue *Q)
{
    Q.base=(QElemType *) malloc(MAXQSIZE * sizeof(QElemType));
    if (!Q.base) exit(OVERFLOW);
    Q.front = Q.rear = 0;
    return OK;
}

2. 求队列长度

int queueLength(SqQueue *Q)
{
    return (Q.rear - Q.front+MAXQSIZE) % MAXQSIZE;
}

3. 入队

Status enQueue (SqQueue *Q, QElemType e)
{
    if((Q.rear+1)%MAXQSIZE == Q.front)  return ERROR;
    Q.base[Q.rear] = e;
    Q.rear = (Q.rear+1) % MAXQSIZE;
    return OK;
}

4. 出队

Status deQueue (SqQueue *Q, QElemType e)
{
    if(Q.front == Q.rear)
    return ERROR;
    e = Q.base[Q.front];
    Q.front = (Q.front+1)%MAXQSIZE;
    return OK;
}

到此这篇关于C利用语言实现数据结构之队列的文章就介绍到这了,更多相关C语言实现数据结构 队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言实现简易三子棋

    C语言实现简易三子棋

    这篇文章主要为大家详细介绍了C语言实现简易三子棋,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • C++中std::find函数介绍和使用场景

    C++中std::find函数介绍和使用场景

    std::find函数是一个非常实用的通用查找算法,适用于各种场景,本文主要介绍了C++中std::find函数介绍和使用场景,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • 详解C++中的析构函数

    详解C++中的析构函数

    这篇文章主要介绍了C++中的析构函数的相关知识,文中讲解非常详细,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 利用Matlab制作抖音同款含褶皱面料图

    利用Matlab制作抖音同款含褶皱面料图

    这篇文章主要介绍了如何利用Matlab制作抖音的同款含褶皱面料图,文中的示例代码讲解详细,对我们学习Matlab有一定帮助,需要的可以参考一下
    2022-03-03
  • 基于字符串移位包含的问题详解

    基于字符串移位包含的问题详解

    本篇文章是对字符串移位包含的问题的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C++的最短路径的弗洛伊德算法案例讲解

    C++的最短路径的弗洛伊德算法案例讲解

    这篇文章主要介绍了C++的最短路径的弗洛伊德算法案例讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++中spdlog的简单使用示例

    C++中spdlog的简单使用示例

    spdlog是一个开源、跨平台、无依赖、只有头文件的C++11日志库,所以这篇文章主要来和大家介绍一下一个简单的spdlog使用示例,感兴趣的小伙伴可以了解一下
    2023-08-08
  • C++ 使用CRC32检测内存映像完整性的实现步骤

    C++ 使用CRC32检测内存映像完整性的实现步骤

    当我们使用动态补丁的时候,那么内存中同样不存在校验效果,也就无法抵御对方动态修改机器码了,为了防止解密者直接对内存打补丁,我们需要在硬盘校验的基础上,增加内存校验,防止动态补丁的运用。
    2021-06-06
  • C++ 中const修饰虚函数实例详解

    C++ 中const修饰虚函数实例详解

    这篇文章主要介绍了C++ 中const修饰虚函数实例详解的相关资料,需要的朋友可以参考下
    2017-06-06
  • 一文搞懂Codec2解码组件

    一文搞懂Codec2解码组件

    这篇文章主要介绍了Codec2解码组件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09

最新评论