zoukankan      html  css  js  c++  java
  • 9.顺序队列、循环队列、链队列

    /*
    4.11 队列的抽象数据类型
    ADT 队列(Queue)
    Data
        同线性表。元素具有相同类型,相邻元素具有前驱和后继关系。
    operation
        InitQueue(*Q)  //初始化操作,建立一个空队列Q。
        DestoryQueue(*Q)   //若队列Q存在,则销毁它。
        ClearQueue(*Q)     //将队列Q清空。
        QueueEmpty(Q)      //若队列Q为空,返回true,否则返回false。
        GetHead(Q, *e)     //若队列Q存在且非空,用e返回队列Q的队头元素。
        EnQueue(*Q, e)      //若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
        DeQueue(*Q, *e)     //删除队列Q中队头元素,并用e返回其值。
        QueueLength(Q)      //返回队列Q的元素个数
    endADT
    */
    
    /*
    4.12 循环队列
    线性表有顺序存储和链式存储,栈是线性表,所以有这两种存储方式。同样,队列作为一种特殊的线性表,
    也同样存在这两种存储方式。
    */
    /*
    4.12.1 队列顺序存储结构的不足
        和顺序线性存储结构一致,定长,会溢出。
        队头为下标0的位置,队尾为下标为1的位置,出队时会移动元素,时间复杂度为O(n)
    4.12.2 循环队列
        循环队列通过移动队头指针的位置,解决出队元素前移时间复杂度为O(n);通过将队尾指针循环,与队头指针
        实现闭合操作,充分利用队列数据位;但是会存在数据溢出问题。
        所以我们直接来看队列的链式存储结构吧
    4.13 队列的链式存储结构及实现
        队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称位链队列。
    
    */
    
    //链队列的结构为:
    /*QElemType类型根据实际情况而定,这里假设为int*/
    typedef int QElemType;
    //结点结构
    typedef struct QNode
    {
        QElemType data;
        struct QNode *next;
    } QNode, *QueuePtr;
    //队列的链表结构
    typedef struct 
    {
        //队头、队尾指针
        QueuePtr front,rear;
    } LinkQueue;
    
    
    //4.13.1队列的链式存储结构--入队操作
    //插入元素e为Q的新的队尾元素,需要结合配图才能理解
    Status EnQueue(LinkQueue *Q, QElemType e)
    {
        QueuePtr s=(QueuePtr)malloc(sizeof(QNode));
        //存储分配失败
        if (!s)
            exit(OVERFLOW);
        s->data = e;
        s->next = NULL;
        //把拥有元素e新节点s赋值给原队尾结点的后继,Q->rear->next = s;
        Q->rear->next = s;
        //把当前的s设置为队尾结点,rear指向s
        Q->rear = s;
        return OK;
    }
    
    //4.13.2 队列的链式存储结构--出栈操作
    //若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
    Status DeQueue(LinkQueue *Q, QElemType *e)
    {
        QueuePtr p;
        if (Q->front == Q->rear)
            return ERROR;
        //将欲删除的队头结点暂存给p
        p = Q->front->next;
        //将欲删除的队头结点的值赋给e
        *e = p->data;
        //将原队头结点后继p->next赋值给头节点后继
        Q->front->next = p->next;
        //若队头是队尾。则删除后将rear指向头结点
        if(Q->rear == p)
            Q->rear = Q->front;
        free(p);
        return OK;
    }
    
    /*
    对于循环队列与链队列的比较,可以从两方面来考虑,从时间上,其实它们的基本操作都是常数时间,即都为O(1),
    不过循环队列是事先申请好空间,使用期间不释放,而对于链队列,每次申请和释放结点也会存在一些时间开销,如果入队
    和出队频繁,则两者还是有细微差异。对于空间上来说,循环队列必须有一个固定的长度,所以就有了存储元素个数和空间
    浪费的问题。而链队列不存在这个问题,尽管它需要一个指针域,会产生一些空间上的开销,但也可以接受,所以在空间上,
    链队列更加灵活。
    总的来说,在可以确定队列长度最大值的情况下,建议用循环队列,如果你无法预估队列的长度时,则用链队列。
    */
  • 相关阅读:
    【面积并】 Atlantis
    【动态前k大 贪心】 Gone Fishing
    【复杂枚举】 library
    【双端队列bfs 网格图建图】拯救大兵瑞恩
    【奇偶传递关系 边带权】 奇偶游戏
    【权值并查集】 supermarket
    CF w4d3 A. Pythagorean Theorem II
    CF w4d2 C. Purification
    CF w4d2 B. Road Construction
    CF w4d2 A. Cakeminator
  • 原文地址:https://www.cnblogs.com/go-ahead-wsg/p/13205192.html
Copyright © 2011-2022 走看看