队列(Queue)是一种线性数据结构,核心规则是 “先进先出”(First In, First Out,简称 FIFO),就像日常生活中的:排队买东西:第一个排队的人最先买到,最后来的人最后买;

队列只允许在一端(队尾,Rear) 添加元素(入队),在另一端(队头,Front) 删除元素(出队),中间的元素无法直接操作

链式队列(LinkQueue)

结构体定义
typedef int ElemType;
typedef struct LinkNode{
    ElemType data; //数据域,存储队列元素
    struct LinkNode *next; //指针域,指向下一个结点的指针
}LinkNode;

front rear 是队列里的重点,用来表示队头队尾,在链表中是指针
带头结点的结构中 front 永远不变,指向头结点

链式队列的控制结构(记录队头/队尾指针)
typedef struct {
    LinkNode *front,*rear; //链表头,链表尾,也可以称为队头,队尾
    //front永远不变,指向头结点
}LinkQueue; 

初始化队列

Q.frontQ.rear 相等,是队列判空的条件 ,是初始化必须做的事。

队列的初始化,使用带头结点的链表来实现
void InitQueue(LinkQueue &Q){
    Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
    Q.front->next=NULL;
}

队列的操作

*入队 :根据先进先出的原则,要从尾部 rear 插入

入队
void EnQueue(LinkQueue &Q,ElemType x){
    LinkNode *pnew=(LinkNode*)malloc(sizeof(LinkNode));
    pnew->data=x;
    pnew->next=NULL;
    Q.rear->next=pnew; //尾指针的next指向pnew,因为从尾部入队
    Q.rear=pnew; //尾指针向后移动
    // 等价于
    // Q.rear=Q.rear->next;
}

*出队 :根据先进先出的原则,要从头部 front 插入,出队时还需要判断 队列是否为空

链表只剩一个结点 时,被删除后,要改变 rear ,一起和 front 指向头结点,否则会成为 野指针

出队
bool DeQueue(LinkQueue &Q,ElemType &x){
    if(Q.rear==Q.front){ //队列为空
        return false;
    }

    LinkNode *q=Q.front->next; //拿到第一个结点,存入q
    x=q->data;
    Q.front->next=q->next; //头结点指向第一个结点的next,让第一个结点断链

    if(Q.rear==q){ //链表只剩一个结点时,被删除后,要改变rear
        Q.rear=Q.front;
    }
    free(q);
    return true;
}

测试看看

通过链表来实现队列
int main() {
    LinkQueue Q;
    InitQueue(Q);

    EnQueue(Q,3);
    EnQueue(Q,4);
    EnQueue(Q,5);
    EnQueue(Q,6);
    EnQueue(Q,7);

    bool ret;
    ElemType element;
    ret=DeQueue(Q,element);
    if(ret){
        printf("DeQueue success element=%d\n",element);
    } else{
        printf("DeQueue failed\n");
    }
    return 0;
}

标签: 数据结构, 队列

添加新评论