算:数据结构与算法(C语言) | 栈和队列——队列

本文围绕C语言中队列数据结构展开,介绍队列是先进先出的线性表,可通过链表或顺序表实现,重点给出链队列的C语言代码,包括构造、插入、删除和销毁操作。还提及循环队列,阐述其解决假溢出的原理及相关代码,如初始化、插入和出队操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据结构与算法(C语言) | 栈和队列——队列

https://blog.youkuaiyun.com/qq_35924276/article/details/81448816 

队列

 •与栈相反,队列是一种先进先出(First In First Out, FIFO)的线性表。只允许在表尾一端进行插入操作而在表头一端进行删除操作。

 

队列既可以用链表实现,也可以用顺序表实现。

跟栈相反的是,栈一般我们用顺序表来实现,而队列我们常用链表来实现,简称为链队列。

    //队列的链式表示和实现
    typedef struct QNode{
        ElemType data;
        struct QNode *next;
    }QNode, *QueuePtr;
    typedef struct{
        QueuePtr front;//队头指针
        QueuePtr rear;//队尾指针
    }LinkQueue;
     

 将队头指针指向链队列的头结点,而队尾指针指向终端结点。(头结点不是必要的)

空队列时,front和rear都指向头结点。

以下将

构造一个空队列、往队列中插入元素、删除元素、销毁队列都用C语言描述

和之前的线性表类似,所以在学习这部分的时候就轻松得多。

 

注意:c语言中->和.的区别——->用于指针, .用于对象

"->"用于指向结构成员,它的左边应为指向该结构类型的指针(结构指针),而"."的左边应为该结构类型的变量(结构变量),如已定义了一个结构体struct student,里面有一个int a;然后有一个结构体变量struct student stu及结构体变量指针struct student *p;且有p=&stu,那么p->a和stu.a表示同一个意思。

 

 实践:编写一个链队列,任意输入一串字符,以#作为结束标志,然后将队列中的元素显示到屏幕上

    #include<stdio.h>
    #include<stdlib.h>
     
    typedef char ElemType;
     
    typedef struct QNode{
        ElemType data;
        struct QNode *next;
    }QNode, *QueuePtr;
    typedef struct{
        QueuePtr front;//队头指针
        QueuePtr rear;//队尾指针
    }LinkQueue;
     
    int InitQueue(LinkQueue *q)
    {
        q->front = q->rear = (QueuePtr)malloc(sizeof(QNode));
        if(!q->front)
        {
            exit(0);//存储分配失败
        }
        q->front->next = NULL;
        return 1;
    }
    int InsertQueue(LinkQueue *q,ElemType e)
    {
        QueuePtr p;
        p = (QueuePtr)malloc(sizeof(QNode));
        if(!q->front)
            exit(0);
        p->data = e;
        p->next = NULL;
        q->rear->next = p;
        q->rear = p;
        return 1;
    }
    int DeleteQueue(LinkQueue *q,ElemType *e)
    {
        QueuePtr p;
     
        if(q->front == q->rear)
            return 0;
     
        p = q->front->next;
        *e = p->data;
        q->front->next = p->next;
     
        if(q->rear == p)//队列中仅有一个元素,删除后队列为空
            q->rear = q->front;
        free(p);
        return 1;
    }
    int DestroyQueue(LinkQueue *q)
    {
        while(q->front)
        {
            q->rear = q->front->next;
            free(q->front);
            q->front = q->rear;
        }
        return 1;
    }
    int main()
    {
        ElemType e;
        LinkQueue q;
        InitQueue(&q);
        printf("请输入一个字符串,并以#号键结束输入:");
        scanf("%c",&e);
     
        while(e !='#')
        {
            InsertQueue(&q, e);
            scanf("%c",&e);
        }
     
        printf("打印队列中的元素:");
        while( q.front != q.rear )
        {
            DeleteQueue(&q,&e);
            printf("%c",e);
        }
        return 0;
    }

                                                      循环队列

队列的顺序存储结构:影响程序效率,也容易出现数组越界的错误。

解决假溢出的办法就是队列满了之后就再从头开始,也就是头尾相接的循环队列。

•循环队列它的容量是固定的,并且它的队头和队尾指针都可以随着元素入出队列而发生改变,这样循环队列逻辑上就好像是一个环形存储空间。

队列空条件:q.front == q.rear

队列满条件:(q.rear +1)%maxsize == 0 (此时队列实际容量为maxsize -1)

    //定义一个循环队列
    #define MAXSIZE 100
    typedef struct
    {
    ElemType *base; // 用于存放内存分配基地址
    // 这里也可以用数组存放
    int front;
    int rear;
    }SqQueue;
     

    //初始化一个循环队列
    Status InitQueue(SqQueue *q)
    {
        q->base = (ElemType *) malloc (MAXSIZE * sizeof(ElemType));
        if( !q->base )//存储分配失败
            exit(0);
        q->front = q->rear = 0;
        return OK;
    }

    //插入元素e
    Status EnQueue(SqQueue *q,ElemType e)
    {
        if((q->rear+1)%MAXSIZE == q->front)
            return ERROR;
        q->base[q->rear] = e;
        q->rear = (q->rear+1)%MAXSIZE;
        return OK;
    }

    //出队列操作
    DeleteQueue(SqQueue *q, ElemType *e)
    {
        if( q->front == q->rear )
            return ERROR; // 队列为空
        *e = q->base[q->front];
        q->front = (q->front+1) % MAXSIZE;
        return OK;
    }

 

 
---------------------  
作者:Shannon333  
来源:优快云  
原文:https://blog.youkuaiyun.com/qq_35924276/article/details/81448816  
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值