数据结构--队列(8)

一、什么是队列

  说到队列我们可能会想到现实世界的排队情况,其实队列这种线性表的结构和现实的队列有着很相似的地方,首先我们在排队的时候只能在队尾进行人员的插入,而我们人员在出去的时候只能是在队头,这就有着一个先进先出的原则,那么回到队列,他也是一种操作受限的线性表,只允许在表的一端插入,而在另一端删除,符合前面所说的先进先出原则。其中这个结构中队头和队尾两个指针,队头是允许出队的一端,队尾是允许插入的一端。

  要实现队列的基本操作:

  InitQueue(&Q):初始化队列,构造一个空队列

  QueueEmpty(&Q):判断队列是否为空

  EnQueue(&Q,x):入队,若队列未满,将x插入,使其称为新的队尾

  DeQueue(&Q,&x):出队,若队列非空,删除队头元素并用x返回

  GetHead(Q,&x):若队列非空获取队头元素由x返回

 

二、顺序队列的基本结构以及操作

结构:

#define MaxSize 100

typedef struct {
    ElemType data[MaxSize];
    int front, rear;                    //队头以及队尾指针
}SeqQueue;

基本操作:

seqQueue.h

#include<stdio.h>

#define MaxSize 100
#define True 1
#define False 0

typedef int ElemType;
typedef int Status;
typedef int Boolean;

typedef struct {
    ElemType data[MaxSize];
    int front, rear;                    //队头以及队尾指针
}SeqQueue;

void InitSeqQueue(SeqQueue *Q);//初始化队列,构造一个空队列
Boolean SeqQueueEmpty(SeqQueue Q);//判断队列是否为空
Status EnSeqQueue(SeqQueue *Q,ElemType x);//入队,若队列未满,将x插入,使其称为新的队尾
Status DeSeqQueue(SeqQueue *Q, ElemType *x);//出队,若队列非空,删除队头元素并用x返回
Status GetSeqQueueHead(SeqQueue Q,ElemType *x);//若队列非空获取队头元素由x返回

seqQueue.c

#include"seqQueue.h"

void InitSeqQueue(SeqQueue *Q) {        //初始化队列,构造一个空队列
    Q->front = 0;
    Q->rear = 0;
}

Status EnSeqQueue(SeqQueue *Q, ElemType x) {        //入队,若队列未满,将x插入,使其称为新的队尾
    if (Q->rear == MaxSize)
        return 0;

    Q->data[Q->rear] = x;
    Q->rear++;

    return 1;
}

Status DeSeqQueue(SeqQueue *Q, ElemType *x) {        //出队,若队列非空,删除队头元素并用x返回

    if (Q->rear == MaxSize)
        return 0;

    *x = Q->data[Q->front];
    Q->front++;

    return 1;
}

Boolean SeqQueueEmpty(SeqQueue Q) {        //判断队列是否为空
    if (Q.front == Q.rear)
        return True;
    else
        return False;
}

Status GetSeqQueueHead(SeqQueue Q, ElemType *x) {        //若队列非空获取队头元素由x返回
    if (Q.front == MaxSize)
        return 0;

    *x = Q.data[Q.front];
    return 1;
}

三、循环队列

 在下图这种情况下的队列,在队列进行是否满的判断下,队列中只有一个元素,但是符合队列满的条件,这是一种假的溢出,所以为了解决这个问题,我们引入了循环队列。

   循环队列是我们认为把队列想象为一个环状,当队列的头指针为MaxSize-1后我们再前进一个位置就自动归0,所以我们可以用取余运算(%)来完成

  初始时:头指针等于尾指针等于0

  出队时:Q.front = (Q.front+1)%Maxsize

  入队时:Q.rear = (Q.rear+1)%MaxSize

  

 

 

   循环队列结构:

#define MaxSize 100

typedef struct {
    ElemType data[MaxSize];
    int front, rear;                    //队头以及队尾指针
    int tag;                                //用来区分队空还是队满的标志量
}CycleSeqQueue;

  循环队列的操作:

  cycleSeqQueue.h

#include<stdio.h>

#define MaxSize 100
#define True 1
#define False 0

typedef int ElemType;
typedef int Status;
typedef int Boolean;

typedef struct {
    ElemType data[MaxSize];
    int front, rear;                    //队头以及队尾指针
    int tag;                                //用来区分队空还是队满的标志量
}CycleSeqQueue;

void InitCycleSeqQueue(CycleSeqQueue *Q);//初始化队列,构造一个空队列
Boolean CycleSeqQueueEmpty(CycleSeqQueue Q);//判断队列是否为空
Status EnCycleSeqQueue(CycleSeqQueue *Q, ElemType x);//入队,若队列未满,将x插入,使其称为新的队尾
Status DeCycleSeqQueue(CycleSeqQueue *Q, ElemType *x);//出队,若队列非空,删除队头元素并用x返回
Status GetCycleSeqQueueHead(CycleSeqQueue Q, ElemType *x);//若队列非空获取队头元素由x返回

  cycleSeqQueue.c

#include"cycleSeqQueue.h"

void InitCycleSeqQueue(CycleSeqQueue *Q) {        //初始化队列,构造一个空队列
    Q->front = 0;
    Q->rear = 0;
    Q->tag = 1;            //默认为1当入队时变为0出队时变为1
}

Status EnCycleSeqQueue(CycleSeqQueue *Q, ElemType x) {        //入队,若队列未满,将x插入,使其称为新的队尾
    if (Q->tag == 0 && Q->front == Q->rear)
        return 0;

    Q->data[Q->rear] = x;
    Q->rear = (Q->rear + 1) % MaxSize;
    Q->tag = 1;
    return 1;
}

Status DeCycleSeqQueue(CycleSeqQueue *Q, ElemType *x) {        //出队,若队列非空,删除队头元素并用x返回
    if (Q->tag == 1 && Q->front == Q->rear)
        return 0;

    *x = Q->data[Q->front];
    Q->front = (Q->front + 1) % MaxSize;
    Q->tag = 0;

    return 1;
}

Boolean CycleSeqQueueEmpty(CycleSeqQueue Q) {        //判断队列是否为空
    if (Q.tag == 0 && Q.front == Q.rear)
        return True;

    return False;
}

Status GetCycleSeqQueueHead(CycleSeqQueue Q, ElemType *x) {        //若队列非空获取队头元素由x返回
    if (Q.tag == 0 && Q.front == Q.rear)
        return 0;

    *x = Q.data[Q.front];
    return 1;
}

四、队列的链式存储结构

  链式存储结构的队列时由两部分组成,一个时队列本身的结构和头指针与尾指针组成的单链表结构:

 

 

   链式存储类型的结构:

typedef struct {        //节点结构体
    ElemType data;
    LinkQueueNode *next;
}LinkQueueNode;

typedef struct {        //队列结构体
    LinkQueueNode *front, *rear;
}LinkQueue;

  链式存储结构的基本操作:

  LinkQueue.h

#include<stdio.h>

#define MaxSize 100
#define True 1
#define False 0

typedef int ElemType;
typedef int Status;
typedef int Boolean;

typedef struct {        //节点结构体
    ElemType data;
    LinkQueueNode *next;
}LinkQueueNode;

typedef struct {        //队列结构体
    LinkQueueNode *front, *rear;
}LinkQueue;

void InitLinkQueue(LinkQueue *Q);//初始化链式循环队列
Boolean LinkQueueEmpty(LinkQueue Q);//判断队列是否为空
Status EnLinkQueue(LinkQueue *Q, ElemType x);//入队,将x插入,使其称为新的队尾
Status DeLinkQueue(LinkQueue *Q, ElemType *x);//出队,若队列非空,删除队头元素并用x返回
Status GetLinkQueueHead(LinkQueue Q, ElemType *x);//若队列非空获取队头元素由x返回

linkQueue.c

#include"linkQueue.h"

void InitLinkQueue(LinkQueue *Q) {        //初始化链式循环队列
    LinkQueueNode *N= (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
    Q->front = N;
    Q->rear = N;
    Q->front->next = NULL;
    Q->rear->next = NULL;
}

Boolean LinkQueueEmpty(LinkQueue Q) {        //判断队列是否为空
    if (Q.front == Q.rear)
        return True;

    return False;
}

Status EnLinkQueue(LinkQueue *Q, ElemType x) {        //入队,将x插入,使其称为新的队尾
    LinkQueueNode *newSpace = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
    newSpace->data = x;
    newSpace->next = NULL;
    Q->rear->next = newSpace;
    Q->rear = newSpace;
    return 1;
}

Status DeLinkQueue(LinkQueue *Q, ElemType *x) {        //出队,若队列非空,删除队头元素并用x返回
    if (Q->front == Q->rear)
        return 0;

    LinkQueueNode *p = Q->front->next;
    *x = p->data;
    Q->front->next = p->next;
    if (Q->rear == p)
        Q->rear = Q->front;

    free(p);
    return True;
}
posted @ 2020-07-14 18:09  熊熊会发光哦  阅读(313)  评论(0编辑  收藏  举报