数据结构-循环(顺序)队列与链队列详解

1、顺序队列的定义

顺序队列是一种运算受限的顺序表,其特殊性在于只允许在一端进行插入操作,而在另一端进行删除操作。这种结构使得顺序队列成为先进先出(FIFO)的线性表

在这里插入图片描述

2、循环队列的定义

循环队列是一种将顺序队列的首尾相连,形成逻辑上的环状结构的队列。这种结构使得队列在到达尾部后可以继续从头开始使用存储空间,从而更有效地利用内存

在这里插入图片描述

一般队列都是循环队列,很少单独出现顺序队列,所以这里直接放上循环队列的一些基本操作

2.1循环队列的基本操作

1)循环队列结构体定义
typedef  struct    /*顺序队列类型定义*/
{
   int front, rear;
   DataType data[MAXNUM];
}SeqQueue;
2)创建空队列
SeqQueue *SQueueCreate()    /*创建一个空队列*/
{  
    SeqQueue *sq = (SeqQueue*)malloc(sizeof(SeqQueue));
    if (sq==NULL)
        printf("溢出!! \n");
    else
        sq->front = sq->rear = 0;
    return sq;
}
3)入队
void  SQueueEnQueue( SeqQueue *sq, DataType x )/* 循环队列的进队操作,x进队 */ 
{
    if( (sq->rear + 1) % MAXNUM == sq->front  )    /*  修改队尾指针  */
        printf( "队列满!\n" );
    else     
    {
    sq->data[sq->rear] = x;
    sq->rear = (sq->rear + 1) % MAXNUM;
    }
}
4)出队
int  SQueueDeQueue( SeqQueue *sq ,DataType *e)
/* 循环队列的出队操作,出队元素存入e中 */ 
{
    if( sq->front == sq->rear )
    {
    printf( "队空!\n" );
    return ERROR;
    }
    else
    { 
         *e=sq->data[sq->front];
         sq->front = (sq->front + 1) % MAXNUM;  /*  修改队头指针  */
         return OK;
    }
}
5)计算队列长度
int SeqQueueLength(SeqQueue *sq)
{
    return (sq->rear-sq->front+MAXSIZE)%MAXNUM;
}

3、链队列的定义

链队列是一种运算受限的线性表,特殊之处在于它只允许在表的一端(队尾)进行插入操作,而在另一端(队头)进行删除操作。这种结构使得链队列具有先进先出的特性,即最早进入队列的元素将最先被删除。

在这里插入图片描述

3.1链队列的基本操作

1)节点结构体定义、链队列结构体定义
typedef struct LQNode/* 链队结点结构 */
{     
    DataType    info;
    struct LQNode *next;
}LQNode;

typedef struct/* 链接队列类型定义 */
{    
    struct LQNode  *front;      /* 头指针 */
    struct LQNode  *rear;      /* 尾指针 */
}LinkQueue;
2)创建空队列
LinkQueue  *LQueueCreateEmpty()/*创建空链队,返回头指针*/
{     
    LinkQueue *plq = (LinkQueue *)malloc(sizeof(LinkQueue));
    if (plq != NULL)
        plq->front = plq->rear = NULL;
    else
    {
        printf("内存不足!! \n");
        return NULL;
    }    
    return plq;
}
3)入队
void  LQueueEnQueue( LinkQueue *plq, DataType x)/*入链队*/
{ 
    LQNode *p = (LQNode *)malloc(sizeof(LQNode));
    if ( p == NULL  )
        printf("内存分配失败!\n");
    else 
    { 
        p->info = x;
        p->next = NULL;
        if (plq->front == NULL)/*原来为空队*/
            plq->front = p;
        else
            plq->rear->next = p;
        plq->rear = p;
    }
}
4)出队
int  LQueueDeQueue( LinkQueue *plq,DataType * x)/*出链队*/
{ 
    LQNode *p;
    if( plq->front == NULL )
    {
        printf( "队列空!!\n " );
        return ERROR;
    }
    else
    { 
        p = plq->front;
        *x=p->info;
        plq->front = plq->front->next;
        free(p);
        return OK;
    }
}

4、循环(顺序)队列与链队列的对比

4.1存储方式

循环队列:基于数组实现,通过循环使用数组空间来存储队列元素。
链队列:基于链表实现,每个节点包含数据部分和一个指向下一个节点的指针。

4.2空间利用

循环队列:需要预先分配固定大小的数组空间。如果队列大小无法预估,可能会出现空间浪费的情况。
链队列:没有固定长度的限制,可以动态调整大小,因此在处理大量数据或不确定数据量的情况下更加灵活。

4.3时间效率

循环队列:插入和删除操作的时间复杂度为O(1),但当队列满时,需要移动大量元素。
链队列:插入和删除操作的时间复杂度也为O(1),但每次操作都涉及内存分配和释放,可能会带来额外的开销。

4.4适用场景

循环队列:适用于需要快速插入和删除操作的场景,且能够预估队列的最大长度。例如,操作系统中的缓冲区管理、广度优先搜索算法(BFS)等。
链队列:适用于数据量较大且需要动态调整大小的场景。例如,任务调度系统、事件驱动编程等。

总的来说,循环队列和链队列各有其优缺点和适用场景。选择哪种数据结构取决于具体的应用需求和环境条件。在实际开发中,可以根据具体情况选择合适的队列结构来实现相应的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值