数据结构 ~ 队列

百度定义

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

举个例子

学生排队买饭。有什么特点呢?当然,你先来,就先打饭,先吃饭。抽象到队列上说,有队头,队尾,要想加入(入队),只能从队尾加,想走(出队),只能从队头走。即:先进先出。

和栈一样,它常见的两种存储是顺序存储和链式存储。

顺序存储结构

用顺序存储时,会遇到这样的情况,数组并没有满,却入不了队(假溢出),原因在于队头没有在数组的0下标处。一般情况下,因为队列会存在假溢出的情况,所以采用循环队列。

定义

#define MAX
typedef struct
{
   int date[MAX];
   int rear;   //控制队尾
   int front;//控制队头
   int count;
}CirQueue;

初始化

void InitQueue(CirQueue *Q)
{
    Q->front = Q->rear = 0;
    Q->count = 0;//计数器置0
}

判空

int QueueEmpty(CirQueue *Q)
{
    return Q->count == 0;//队列无元素为空
}

判满

int QueueFull(CirQueue *Q)
{
    return Q->count == Max;//队中元素个数等于max时队满
}

入队列

void EnQueue(CirQueuq *Q,int x)
{
    if(QueueFull((Q)) {
        Error("Queue overflow");//队列满了
    }
    Q->count++;//队列元素个数加1
    Q->data[Q->rear] = x;//新元素插入队尾
    Q->rear = (Q->rear + 1) % Max;//用的是循环,当满时头尾相差一个空间,用于区别满和不满。
}

出队列

DataType DeQueue(CirQueue *Q)
{
    int temp;
    if(QueueEmpty((Q)) {
        Error("QueueEmpty"); //队空
    }
    temp = Q->data[Q->front];
    Q->count--;//队列元素个数减1
    Q->front = (Q->front + 1) % Max; //循环意义下的头指针加1
    return temp;
}

取队头元素

int QueueFront(CirQueue *Q)
{
    if(QueueEmpty(Q)) {
        Error("Queue if empty.");
    }
    return Q->data[Q->front];
}

链式存储结构

定义

typedef struct Queue//结点结构
{
    int data;
    struct Queue *next;
} Queue;

typedef struct  //队列的链表结构
{
    Queue *front; //队头、队尾指针
    Queue *rear;
} LinkQueue;

初始化

LinkQueue *InitQueue(LinkQueue *q)
{
    q->front = q->next =(Queue*)malloc(sizeof(Queue));
    q->front->next = NULL;
    return q;
}

判空

int QueueEmpty(CirQueue *Q)
{
    ifq->front == q->rear){
        return 1;
    }
    return 0;
}

入队列

LinkQueue *EnQueue(LinkQueue *q, int e)
{
    Queue *p = (Queue*)malloc(sizeof(Queue));//为插入节点分配空间
    if(!p) {
        //分配空间失败
        cout<<"not enough memory!"<<endl;
    }
    else {
        //建节点
        p->data = e; //为插入节点数据域赋值
        p->next = NULL;//为插入节点指针域赋值
        //实现插入
        q->rear->next = p;//插入到队尾
        q->rear = p;//队尾指针重新指向新任队尾
    }
    return q;
}   

元素出队

LinkQueue *DeQueue(LinkQueue *q)
{
    Queue *p;
    if(q->front == q->rear) {
        cout<<"LinkQueue is NULL"<<endl;
    }
    else {
        p = q->front->next;//将欲删除的队头结点暂存给p
        int e = p->data;//把队头数据赋给e
        cout<<"delete: "<<e<<endl;
        q->front->next = p->next;//删除,将原队头结点的后继p->next赋值给头结点后继
        if(q->rear == p) {
            //若队头就是队尾,则删除后将rear指向头结点
            cout<<"链队列数据全部删除完毕!"<<endl;
            q->rear = q->front;
        }
        free(p);
    }
    return q;
}

返回头元素

void GetQHead(LinkQueue *q)
{
    Queue *p;
    if(q->front == q->rear) {
         cout<<"LinkQueue  is NULL"<<endl;
    }
    else {
        p = q->front->next;//队头
        cout<<"队头元素:"<<p->data<<endl;
    }
}

求队列长度

int QueueLength(LinkQueue *q)
{
    int length = 0;
    Queue *p;
    p = q->front->next;//队头
    while(p) {
        length++;
        p = p->next;
    }
   return length;
}

以上,欢迎留言交流~

猜你喜欢

转载自blog.csdn.net/breakpoints_/article/details/80454352