队列的相关操作--c语言

•队列的顺序存储

只允许在表的一端进行插入,在另一端删除的就是队列
队列也有顺序存储方式

//顺序队列
typedef struct {
    ElemType data[MaxSize];
    int front;    //队头指针
    int rear;   //队尾指针,在这里队尾指针指向的队尾元素的下一个数组坐标位置
} SqQueue;

顺序队列不易于判满,为此引入循环队列的概念
 
 

•循环队列

 

1.初始化,判空

//初始化队列
void InitQueue(SqQueue &Q)
{
    //队头指针和队尾指针同时指向第0个元素
    Q.rear = 0;    //队尾指针指向的队尾元素的下一个数组坐标位置
    Q.front = 0;
}
//判空
bool EmptyQueue(SqQueue Q)
{
    //通过判断队头指针与队尾指针是否指向同一个位置来判空
    if (Q.rear == Q.front) {
        return true;
    } else {
        return false;
    }
}

 

2.入队,出队和读取队头

//入队
bool EnQueue(SqQueue &Q, ElemType e)
{
    if ((Q.rear + 1) % MaxSize == Q.front) {
        //判断是否队满
        //队尾指针的下一位是队头则队满
        return false;
    }

    Q.data[Q.rear] = e;

    //此时队尾指针更新到下一个位置
    Q.rear = (Q.rear + 1) % MaxSize;
    //设队满为5(0~4),如果原本队尾指针指着最后一个位置4的话,
    //再进行入队,队尾指针+1为5并取模,得到的就是0
    //前提是队尾指针指向队尾的下一个数组坐标

    return true;
}
//出队
bool DeQueue(SqQueue &Q, ElemType &e)
{
    if (Q.rear == Q.front) {
        //判断是队空
        return false;
    }

    e = Q.data[Q.front];
    Q.front = (Q.front + 1) % MaxSize;    //更新队头指针
    return true;
}

//读取队头
bool GetHead(SqQueue Q, ElemType &e)
{
    if (Q.rear == Q.front) {
        //判断是队空
        return false;
    }

    e = Q.data[Q.front];
    return true;
}

 

4.判满

1.上述代码判断队满是通过判断(Q.rear + 1) % MaxSize == Q.front,即队尾指针的下一个元素位置是否为队头指针。此时会浪费队尾指针所在的那块空间
2.通过在队列结构体里增加size记录队列当前长度,当size = MaxSize时队满,此时不会浪费内存空间
3.通过在队列结构体里增加tag记录最近一次到操作是插入还是删除。当Q.rear == Q.front时,tag==0则是删除操作,此时队空。tag==1则是插入操作,此时队满

 

5.代码汇总

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

#define ElemType int
#define MaxSize 10

typedef struct {
    ElemType data[MaxSize];
    int front;    //队头指针
    int rear;   //队尾指针
} SqQueue;

//--------------------------------------------------------------------
//初始化队列
void InitQueue(SqQueue &Q)
{
    //队头指针和队尾指针同时指向第0个元素
    Q.rear = 0;    //队尾指针指向的队尾元素的下一个数组坐标位置
    Q.front = 0;
}
//--------------------------------------------------------------------


//--------------------------------------------------------------------
//判空
bool EmptyQueue(SqQueue Q)
{
    //通过判断队头指针与队尾指针是否指向同一个位置来判空
    if (Q.rear == Q.front) {
        return true;
    } else {
        return false;
    }
}
//--------------------------------------------------------------------


//--------------------------------------------------------------------
//入队
bool EnQueue(SqQueue &Q, ElemType e)
{
    if ((Q.rear + 1) % MaxSize == Q.front) {
        //判断是否队满
        //队尾指针的下一位是队头则队满
        return false;
    }

    Q.data[Q.rear] = e;

    //此时队尾指针更新到下一个位置
    Q.rear = (Q.rear + 1) % MaxSize;
    //设队满为5(0~4),如果原本队尾指针指着最后一个位置4的话,
    //再进行入队,队尾指针+1为5并取模,得到的就是0
    //前提是队尾指针指向队尾的下一个数组坐标

    return true;
}

//出队
bool DeQueue(SqQueue &Q, ElemType &e)
{
    if (Q.rear == Q.front) {
        //判断是队空
        return false;
    }

    e = Q.data[Q.front];
    Q.front = (Q.front + 1) % MaxSize;    //更新队头指针
    return true;
}

//读取队头
bool GetHead(SqQueue Q, ElemType &e)
{
    if (Q.rear == Q.front) {
        //判断是队空
        return false;
    }

    e = Q.data[Q.front];
    return true;
}

//--------------------------------------------------------------------


 
 

•队列的链式存储

就是一个有队头指针和队尾指针的单链表,代码的基本逻辑和单链表相同,只是队列只能从队尾入队,队头出队,不能像单链表那样随便增删
不同于顺序队列,具有单链表特性的链队列无需判满。

//链队列结点
typedef struct LinkNode {
    ElemType data;
    struct LinkNode *next;
} LinkNode;
//链队列
typedef struct {
    LinkNode *front, *rear;   //队头指针和队尾指针
} LinkQueue;

 

1.初始化,判空

//初始化(带头结点)
void InitQueue(LinkQueue &Q)
{
    Q.front = (LinkNode*)malloc(sizeof(LinkNode));
    Q.rear = Q.front;
    Q.front->next = null;
}
//判空(带头结点)
bool IsEmpty(LinkQueue Q)
{
    //判定条件也可以是Q.front->next == null
    if(Q.rear = Q.front){
        return true;
    }else{
        return false;
    }
}

 

2.入队,出队

//入队(带头结点)
bool EnQueue(LinkQueue &Q, ElemType x)
{
    LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));    //申请新节点指针

    if (s == null) {
        return false;
    }

    s->data = x;
    s->next = null;

    //rear是LinkNode *型,所以声名s也需要是LinkNode *型
    Q.rear->next = s;    //在队尾插入s
    Q.rear = s;    //更新rear的指针域
    return ture;
}
//出队(带头结点)
bool DeQueue(LinkQueue &Q, ElemType &x)
{
    if(Q.rear = Q.front){
        //判空
        return false;
    }

    LinkNode *p = Q.front->next;    //p指向被删除结点
    x = p->data;
    Q.front->next = p->next;    //修改头结点的后项指针

    if(Q.rear == p){
        //当出队的是最后一个结点,需要修改尾指针
        Q.rear = Q.front;
    }

    free(p);
    return true;
}

 

5.代码汇总

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

#define ElemType int
#define null NULL

//链队列结点
typedef struct LinkNode {
    ElemType data;
    struct LinkNode *next;
} LinkNode;
//链队列
typedef struct {
    LinkNode *front, *rear;   //队头指针和队尾指针
} LinkQueue;


//------------------------------------------------------------
//初始化(带头结点)
void InitQueue(LinkQueue &Q)
{
    Q.front = (LinkNode*)malloc(sizeof(LinkNode));
    Q.rear = Q.front;
    Q.front->next = null;
}
//判空(带头结点)
bool IsEmpty(LinkQueue Q)
{
    //判定条件也可以是Q.front->next == null
    if (Q.rear = Q.front) {
        return true;
    } else {
        return false;
    }
}
//------------------------------------------------------------


//------------------------------------------------------------
//入队(带头结点)
bool EnQueue(LinkQueue &Q, ElemType x)
{
    LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));    //申请新节点指针

    if (s == null) {
        return false;
    }

    s->data = x;
    s->next = null;

    //rear是LinkNode *型,所以声名s也需要是LinkNode *型
    Q.rear->next = s;    //在队尾插入s
    Q.rear = s;    //更新rear的指针域
    return ture;
}

//出队(带头结点)
bool DeQueue(LinkQueue &Q, ElemType &x)
{
    if(Q.rear = Q.front){
        //判空
        return false;
    }

    LinkNode *p = Q.front->next;    //p指向被删除结点
    x = p->data;
    Q.front->next = p->next;    //修改头结点的后项指针

    if(Q.rear == p){
        //当出队的是最后一个结点,需要修改尾指针
        Q.rear = Q.front;
    }

    free(p);
    return true;
}
//------------------------------------------------------------

 
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值