数据结构(C语言版)——4.1、顺序队列实现

4.1、顺序队列实现

4.1.1、顺序队列说明

  • 和顺序表类似。顺序队列即队列的顺序存储结构是利用一组地址连续的存储单元依次存放 自队头 到队尾 的数据元素,同时附设指针 front 指示队头元素在顺序队列中的位置,设指针 rear 指示队尾元素在顺序队列中的位置。
  • 通常习惯做法,鉴于C语言中数组的下标约定从整数 0 开始,则为了方便,这里队头与队尾指针 front 与 rear 设为 int 变量。
  • 初始状态,front = rear 表示队列为空,每当插入一个新的队列元素时,rear 增 1 (只能从队尾入队);删除一个队列元素时,front 增 1 (只能从队头出队)。因此非空队列中的队尾指针 rear 始终在队尾元素的下一个位置上;队头指针 front 始终在队头元素所在位置。

在这里插入图片描述
其中,base 为队列的基址。

4.1.2、顺序队列的优缺点与适用场合

  • 由于在 front 处删除队列元素后,front 只能向前移动,从而使 base 到 front 间的空间无法再被利用,故顺序队列过于浪费空间。
  • 如下图所示,删除一个队头后,base [0] 处的存储单元已无法再被使用(由于队列只能从队尾插入)。故队列的顺序存储结构很少被应用,这时循环队列的价值得以体现(顺序结构的循环队列)。
    在这里插入图片描述
    4.1.3、存储结构定义与头文件声明

(1)存储结构定义

  • 由于顺序队列不像顺序栈那样,当初始分配的存储空间已满时,易于实现空间的追加分配,所以顺序队列结构没有空间分配增量。
  • 访问连续存储空间,基址 base 是必须的,就像数组名那样。队头指示 front 、队尾指示 rear 设为整型(上述已分析)。
#define QUEUE_INIT_SIZE 10 //连续存储空间初始分量
typedef struct
{
   
    ElemType *base; //类似与数组的首地址
    int front;      //队头指示
    int rear;       //队尾指示
} SeqQueue;

(2)头文件声明

  • 头文件声明包括函数结果状态代码 OK、ERROR,数据元素类型 ElemType ,顺序队列的基本操作的函数原型声明,以及相应的库文件。
    注:由于C语言不存在引用,需用传址,如InitQueu()、DestoryQueue()等需要改变顺序队列内容的操作,需要传递结构体类型变量SeqQueue的地址。即,形参声明为指针类型,实参用取址符
#ifndef SEQQUEUE_H
#define SEQQUEUE_H

#define OK 1
#define ERROR 0

typedef int Status;   //自定义函数类型,其值是函数结果的状态代码
typedef int ElemType; //自定义数据类型
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#define QUEUE_INIT_SIZE 10 //连续存储空间初始分量
typedef struct
{
   
    ElemType *base; //类似与数组的首地址
    int front;      //队头指示
    int rear;       //队尾指示
} SeqQueue;
//链队列基本操作的函数原型说明
Status InitQueue(SeqQueue *Q);
//构造一个空队列
Status DestoryQueue(SeqQueue *Q);
//销毁队列 Q
Status ClearQueue(SeqQueue *Q);
//置空队列 Q
bool QueueEmpty(SeqQueue Q);
//判断队列是否为空
int QueueLength(SeqQueue Q);
//返回队列 Q 的元素个数,即队列长度
Status GetHead(SeqQueue Q, ElemType *e);
//若队列不为空,则用 e 获取 Q 的队头元素,并返回OK;否则返回ERROR
Status EnQueue(SeqQueue *Q, ElemType e);
//插入元素 e 为队列 Q 的新队尾元素
Status DeQueue(SeqQueue *Q, ElemType *e);
//若队列不为空,则删除 Q 的队头元素,用 e 获取其值,并返回OK;否则返回ERROR
Status QueueTraverse(SeqQueue Q /*,visit()*/);
//从队头到队尾依次调用函数 visit(),这里简化为输出
#endif

4.1.4、主要操作实现与思路

(1)初始化 InitQueue()

  • 顺序队列的初始化操作就是为顺序队列分配一个预定义大小的存储空间。其中,base 始终指向队列的基地址(即 base 是顺序队列结构存在的标志,若 base = NULL,则表明该队列结构不存在)。
  • 队头、队尾指针的初始化均指向队列空间的基址,即 0 位置处。
  • 该操作要修改队列结构体中 S 的内容,故要传递 SeqQueue 类型变量的地址,从而在该函数体中,S 是指向 SeqQueue 的指针。
    在这里插入图片描述
Status InitQueue(SeqQueue *Q)
{
   
    Q->base = (ElemType *)malloc(sizeof(ElemType) * QUEUE_INIT_SIZE);
    assert(Q->base != NULL);

    Q->front = Q->rear = 0; //空队列时,二者均指向基址,即类似数组a[0]处
    return OK;
}

(2)置空 ClearQueue()

  • 对于顺序队列而言,只需令 front == rear == 0 即可。front == rear 已将当前队列置为空,将它们赋为 0 的意义在于,置空后的队列像刚初始化的队列一样,方便重新插入元素。
  • 当再次更新该顺序队列时,直接给新值时,原数据直接被覆盖。故置空顺序队列时,不需要操作顺序队列中的数据值。
  • 同样需要传递地址
Status ClearQueue(SeqQueue *Q)
{
   
    Q->front = Q->rear = 0; //将队尾指向队尾即可,重新写入时,要从队尾重新开始
    return OK;
}

(3)销毁 DestoryQueue()

  • 区别与置空操作,销毁将释放顺序队列的存储空间,而置空不是。
  • 由于顺序队列的存储单元是连续的,故直接 free 操作基地址即可。注意释放后指针的赋 NULL(避免随机指针的存在,这是大忌)。
Status DestoryQueue
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值