zoukankan      html  css  js  c++  java
  • 数据结构--队列(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;
    }
  • 相关阅读:
    __cdecl, __stdcall, __fastcall,__pascal调用区别
    Windows Hook原理与实现
    C语言四大存储区域总结
    MFC DestroyWindow、OnDestroy、OnClose 程序关闭相关
    VC++动态链接库DLL编程深入浅出"
    windows 安全模型简介
    获取当前焦点窗口进程名
    获取IE URL
    DLL编写中extern “C”和__stdcall的作用
    Django2支持跨域方法
  • 原文地址:https://www.cnblogs.com/bearcanlight/p/13300047.html
Copyright © 2011-2022 走看看