• 四.队列


    队列的概念

    • 队列(Queue):也是运算受限的线性表。是一种先进先出FIFO(Last In First Out)的线性表。只允许在表的一端进行插入,而在另一端进行删除。
    • 队首(front):允许进行删除的一端称为队首。
    • 队尾(rear):允许进行插入的一端称为队尾。

    队列的抽象数据类型

    ADT Queue{
    数据对象:(D={a_i|a_i∈ElemSet,i=1,...,n,n≥0})
    数据关系:(R={<a_{i-1},a_i>|a_{i-1},a_i∈D,i=2,3,...n})
    约定(a_1)端为队首,(a_n)端为队尾。
    基本操作:
    Create():创建一个空队列;
    EmptyQue():若队列为空,则返回true,否则返回false;
    ……
    InsertQue(x):向队尾插入元素x;
    DeleteQue(x):删除队首元素x;
    }ADT Queue

    队列的顺序表示和实现

    队列的顺序存储表示

    利用一组连续的存储单元(一维数组)依次存放从队首到队尾的各个元素,称为顺序队列。类型定义如下:

    #define MAX_QUEUE_SIZE 100 
    typedef struct queue
    { ElemType Queue_array[MAX_QUEUE_SIZE ]; 
      int front;
      int rear;     
    }SqQueue;
    

    设立一个队首指针front,一个队尾指针rear,分别指向队首和队尾元素。
    初始化:front=rear=0
    入队:将新元素插入rear所指的位置,然后rear加1
    出队:删去front所指的元素,然后加1并返回被删元素
    队列为空:front=rear
    队满:rear=MAX_QUEUE_SIZE -1或front=rear

    循环队列

    为充分利用向量空间,克服“假溢出”现象的方法是:将为队列分配的向量空间看成为一个首尾相接的圆环,并称这种队列为循环队列(Circular Queue)。
    在循环队列中进行出队、入队操作时,队首、队尾指针仍要加1,朝前移动。只不过当队首、队尾指针指向向量上界(MAX_QUEUE_SIZE )时,其加1操作的结果是指向向量的下界0。
    这种循环意义下的加1操作可以描述为:i=(i+1)%MAX_QUEUE_SIZE
    显然,为循环队列所分配的空间可以被充分利用,除非向量空间真的被队列元素全部占用,否则不会上溢。
    因此,真正实用的顺序队列是循环队列。
    1)rear所指的单元始终为空
    2)循环队列为空:front=rear
    3)循环队列满:(rear+1)%MAX_QUEUE_SIZE=front

    • 队列初始化
    SqQueue Init_CirQueue(void)
    {  SqQueue Q;
       Q.front=Q.rear=0;
       return(Q);
    }
    
    • 入队操作
    Status Insert_CirQueue(SqQueue Q,ElemType e)
    /*将数据元素e插入到循环队列Q的队尾*/
    {  if((Q.rear+1)%MAX_QUEUE_SIZE ==Q.front)
       return ERROR;/*队满,返回错误标志*/
       Q.Queue_array[Q.rear]=e;/*元素e入队*/
       Q.rear=(Q.rear+1)%MAX_QUEUE_SIZE ;
       /*队尾指针向前移动*/
       return OK;/*入队成功*/
    }
    
    • 出队操作
    Status Delete_CirQueue(SqQueue Q,ElemType *x)
    /*将循环队列Q的队首元素出队*/
    {  if(Q.front+1==Q.rear)
       return ERROR;/*队空,返回错误标志*/
       *x=Q.Queue_array[Q.front];/*取队首元素*/
       Q.front=(Q.front+1)%MAX_QUEUE_SIZE ;
       /*队首指针向前移动*/
       return OK;
    }
    

    队列的链式表示和实现

    队列的链式存储表示

    队列的链式存储结构简称为链队列,它是限制仅在表头进行删除操作和表尾进行插入操作的单链表。
    需要两类不同的节点:数据元素节点,队列的队首指针和队尾指针的节点。

    /*数据元素节点类型的定义:*/
    typedef struct QNode
    { ElemType data; 
      struct QNode *next;    
    }QNode;
    
    /*指针结点类型的定义:*/
    typedef struct link_queue
    { QNode *front,*rear;    
    }Link_Queue;
    
    • 链队列的初始化
    LinkQueue *Init_LinkQueue(void)
    {  LinkQueue *Q;
       QNode *p;
       p=(QNode *)malloc(sizeof(QNode));/*开辟头结点*/
       p->next=NULL;
       Q=(LinkQueue *)malloc(sizeof(LinkQueue));/*开辟链队的指针结点*/
       Q.front=Q.rear=p;
       return(Q);
    }
    
    • 入队操作
    Status Insert_LinkQueue(LinkQueue *Q,ElemType e)
    /*将数据元素e插入到链队列Q的队尾*/
    {  p=(QNode *)malloc(sizeof(QNode));
       if(!p)
       return ERROR;/*申请新结点失败,返回错误标志*/
       p->data=e;
       p->next=NULL;/*形成新结点*/
       Q.rear->=p;
       Q.rear=p;/*新结点插入到队尾*/
       return OK;
    }
    
    • 出队操作
    Status Delete_LinkQueue(LinkQueue *Q,ElemType *x)
    /*将循环队列Q的队首元素出队*/
    {  QNode *p;
       if(Q.front==Q.rear)
       return ERROR;/*队空,返回错误标志*/
       p=Q.front->next;/*取队首结点*/
       *x=p->data;
       Q.front->next=p->next;/*修改队首指针*/
       if(p==Q.rear)
       Q.rear=Q.front
       /*当队列只有一个结点时应防止丢失队尾指针*/
       free(p);
       return OK;
    }
    
  • 相关阅读:
    Ruby编程语言学习笔记1
    SQL SERVER 2008 基础知识
    SQLServer批量插入数据的两种方法
    JQuery基础
    wpf首次项目开发技术总结之access数据库
    wpf首次项目开发技术总结wpf页面
    c#项目开发常见问题
    pl/sql基础
    wpf 开发应用初次总结
    博客园安家
  • 原文地址:https://www.cnblogs.com/jianxiong0117/p/9437141.html
Copyright © 2020-2023  润新知