队列的介绍

1.队列的概念

队列性质:先进先出

队列的操作:

入队

出队

2.链式队列

为了实现队列的先进先出的原理,链式存储里面可以采用头插法和尾删法或者尾插法和头删法实现功能,但是尾插法和尾删法都需要每次遍历链表,效率比较低

所以我们可以定义两个指针变量,一个front保存头结点的地址,另一个rear保存最后一个结点的地址

入队操作时将新节点插入到rear对应结点的后面,然后rear保存最后一个结点的地址,出队操作就是将头结点后面的结点删除

3. 链式队列的操作

3.1创建一个空的队列

//创建一个空的队列
linkqueue *LinkqueueCreate()
{
    //创建两个指针
    linkqueue *q = (linkqueue *)malloc(sizeof(linkqueue));
    
    //创建一个头结点并且让next指针保存NULL标识为空
    q->front = (linknode *)malloc(sizeof(linknode));
    q->rear = q->front;
    q->front->next = NULL;

    return q;
}

3.2入队

//入队
void LinkqueueInput(linkqueue *q, DataType value)
{
    //申请空间并赋值
    linknode *temp = (linknode *)malloc(sizeof(linknode));
    temp->data = value;
    temp->next = NULL;

    //将新结点插入到rear对应结点的后面
    //rear结点的指针域保存新结点的地址
    q->rear->next = temp;
    //新结点的指针域保存NULL
    temp->next = NULL;

    //rear保存新插入结点的地址
    q->rear = temp;

    return ;
}

3.3出队

//出队
DataType LinkqueueOutput(linkqueue *q)
{
    if(q->front->next == NULL)
    {
        printf("队列为空\n");
        return (DataType)-1;
    }

    //将front对应结点的后面的结点删除
    linknode *temp = q->front->next;
    q->front->next = temp->next;

    DataType value = temp->data;

    free(temp);
    temp = NULL;
    
    //当最后一个结点删除之后,需要将rear指针指向头结点
    if(q->front->next == NULL)
    {
        q->rear = q->front;
    }


    return value;
}

4.相关代码

linqueue.h

#ifndef _LINKQUEUE_H_
#define _LINKQUEUE_H_

#include <stdio.h>
#include <stdlib.h>

//定义数据类型
typedef int DataType;

//定义结点结构体
typedef struct node{
    DataType data;
    struct node *next;
}linknode;

//定义结构体便于返回操作链式队列的两个指针
typedef struct{
    linknode *front; //保存头结点的地址
    linknode *rear; //每次保存最后一个结点的地址
}linkqueue;

//创建一个空的队列
linkqueue *LinkqueueCreate();
//入队
void LinkqueueInput(linkqueue *q, DataType value);
//出队
DataType LinkqueueOutput(linkqueue *q);

#endif

linkqueue.c

#include "linkqueue.h"

//创建一个空的队列
linkqueue *LinkqueueCreate()
{
    //创建两个指针
    linkqueue *q = (linkqueue *)malloc(sizeof(linkqueue));
    
    //创建一个头结点并且让next指针保存NULL标识为空
    q->front = (linknode *)malloc(sizeof(linknode));
    q->rear = q->front;
    q->front->next = NULL;

    return q;
}

//入队
void LinkqueueInput(linkqueue *q, DataType value)
{
    //申请空间并赋值
    linknode *temp = (linknode *)malloc(sizeof(linknode));
    temp->data = value;
    temp->next = NULL;

    //将新结点插入到rear对应结点的后面
    //rear结点的指针域保存新结点的地址
    q->rear->next = temp;
    //新结点的指针域保存NULL
    temp->next = NULL;

    //rear保存新插入结点的地址
    q->rear = temp;

    return ;
}

//出队
DataType LinkqueueOutput(linkqueue *q)
{
    if(q->front->next == NULL)
    {
        printf("队列为空\n");
        return (DataType)-1;
    }

    //将front对应结点的后面的结点删除
    linknode *temp = q->front->next;
    q->front->next = temp->next;

    DataType value = temp->data;

    free(temp);
    temp = NULL;
    
    //当最后一个结点删除之后,需要将rear指针指向头结点
    if(q->front->next == NULL)
    {
        q->rear = q->front;
    }


    return value;
}

main.c

#include "linkqueue.h"

int main(int argc, char const *argv[])
{
    linkqueue *queue = LinkqueueCreate();

    LinkqueueInput(queue, 100);
    LinkqueueInput(queue, 200);
    LinkqueueInput(queue, 300);
    LinkqueueInput(queue, 400);
    LinkqueueInput(queue, 500);
    LinkqueueInput(queue, 600);

    printf("出队:%d\n", LinkqueueOutput(queue));
    printf("出队:%d\n", LinkqueueOutput(queue));
    printf("出队:%d\n", LinkqueueOutput(queue));
    printf("出队:%d\n", LinkqueueOutput(queue));
    printf("出队:%d\n", LinkqueueOutput(queue));
    printf("出队:%d\n", LinkqueueOutput(queue));
    printf("出队:%d\n", LinkqueueOutput(queue));
    
    LinkqueueInput(queue, 666);
    LinkqueueInput(queue, 777);
    LinkqueueInput(queue, 888);
    printf("出队:%d\n", LinkqueueOutput(queue));
    printf("出队:%d\n", LinkqueueOutput(queue));
    printf("出队:%d\n", LinkqueueOutput(queue));
    
    return 0;
}

5. 顺序队列(循环队列)

sequeue.h

#ifndef _SEQUEUE_H_
#define _SEQUEUE_H_

#include <stdio.h>
#include <stdlib.h>

//顺序队列又称之为循环队列
//为了能判断队列为空为满,
//所以如果要存储NUM元素的数组应该定义元素的个数为NUM+1

#define NUM 32
#define N (NUM+1)

//定义数据类型
typedef int DataType;
//定义结构体
typedef struct{
    DataType data[N];
    int front; //保存出队的元素下标
    int rear; //保存入队位置
}sequeue;

//创建一个空的循环队列
sequeue *SequeueCreate();
//判断循环队列是否为满
int SequeueIsFull(sequeue *sq);
//判断循环队列是否为空
int SequeueIsEmpty(sequeue *sq);
//入队
void SequeueInput(sequeue *sq, DataType value);
//出队
DataType SequeueOutput(sequeue *sq);


#endif

sequeue.c

#include "sequeue.h"

//创建一个空的循环队列
sequeue *SequeueCreate()
{
    //申请空间
    sequeue *sq = (sequeue *)malloc(sizeof(sequeue));
    //初始状态让front和rear都保存0标识为空
    sq->front = sq->rear = 0;

    return sq;
}

//判断循环队列是否为满
int SequeueIsFull(sequeue *sq)
{
    return ((sq->rear + 1) % N) == sq->front ? 1 : 0;
}

//判断循环队列是否为空
int SequeueIsEmpty(sequeue *sq)
{
    return sq->front == sq->rear ? 1 : 0;
}

//入队
void SequeueInput(sequeue *sq, DataType value)
{
    if(SequeueIsFull(sq))
    {
        printf("队列为满\n");
        return ;
    }

    //将数据保存在rear对应的数组位置上
    sq->data[sq->rear] = value;
    //rear保存下一个元素的下标
    sq->rear = (sq->rear + 1) % N;

    return ;
}

//出队
DataType SequeueOutput(sequeue *sq)
{
    if(SequeueIsEmpty(sq))
    {
        printf("队列为空\n");
        return (DataType)-1;
    }

    //定义临时变量保存要出队的数据
    DataType value = sq->data[sq->front];

    //front后移保存下一个要出队的数据的下标
    sq->front = (sq->front + 1) % N;

    return value;
}

main.c

#include "sequeue.h"

int main(int argc, char const *argv[])
{
    sequeue *sq = SequeueCreate();

    SequeueInput(sq, 100);
    SequeueInput(sq, 200);
    SequeueInput(sq, 300);
    SequeueInput(sq, 400);
    SequeueInput(sq, 500);
    SequeueInput(sq, 600);

    while(!SequeueIsEmpty(sq))
    {
        printf("出队:%d\n", SequeueOutput(sq));
    }
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小徐的记事本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值