#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct node {
    int data;
    struct node *next;
}NODE, *PNODE;

typedef struct queue {
    PNODE front;
    PNODE rear;
}QUEUE, *PQUEUE;

void init(PQUEUE pQ);
void en_queue(PQUEUE, int);
bool out_queue(PQUEUE, int *);
void traverse(PQUEUE);
void clear(PQUEUE);

void clear(PQUEUE pQ)
{
    printf("clear...\n");
    if (pQ->front->next == NULL)
        return;

    PNODE p = pQ->front->next;
    PNODE q;
    while (p) {
        q = p;
        p = p->next;
        free (q);
    }

    pQ->front->next = NULL;
    pQ->rear = pQ->front;
}

void traverse(PQUEUE pQ)
{
    printf("traverse: ");
    PNODE p;
    // 也可以改为pQ->front == pQ->rear来判断是否为空
    if (pQ->front->next == NULL) {
        printf("queue empty!\n");
        return;
    }
    
    p = pQ->front->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    putchar('\n');
}

bool out_queue(PQUEUE pQ, int *pVal)
{
    printf("out_queue...");
    PNODE tmp;

    if (pQ->front->next == NULL) {
        printf(" failed, queue empty!\n");
        return false;
    }

    tmp = pQ->front->next; 
    *pVal = tmp->data;

    pQ->front->next = tmp->next;
    // 最后一个节点出队特殊处理
    if (tmp->next == NULL)
        pQ->rear = pQ->front;
    free(tmp);

    printf("success, value: %d\n", *pVal);
    return true;
}

void en_queue(PQUEUE pQ, int val)
{
    printf("en_queue %d", val);
    PNODE pNew;
    pNew = (PNODE)malloc(sizeof(NODE));
    if (!pNew) {
        printf(" en_queue malloc error!\n");
        exit(-1);
    }
    pNew->data = val;
    pNew->next = NULL;

    pQ->rear->next = pNew;
    pQ->rear = pNew;

    // 首次入队特殊处理
    if (pQ->front->next == NULL)
        pQ->front->next = pNew;

    printf(" success.\n");
}

void init(PQUEUE pQ)
{
    // front, rear都指向头节点
    pQ->front = pQ->rear = (PNODE)malloc(sizeof(NODE));
    if (! pQ->front) {
        printf("init malloc error!\n");
        exit(-1);
    }
    pQ->front->next = NULL;
}

int main(void)
{
    QUEUE q;
    int val;

    init(&q);
    printf("f %p, r %p, fnext %p, rnext %p\n", q.front, q.rear, q.front->next, q.rear->next);
    traverse(&q);
    out_queue(&q, &val);
    en_queue(&q, 21);
    printf("f %p, r %p, fnext %p, rnext %p\n", q.front, q.rear, q.front->next, q.rear->next);
    en_queue(&q, 22);
    printf("f %p, r %p, fnext %p, rnext %p\n", q.front, q.rear, q.front->next, q.rear->next);
    en_queue(&q, 23);
    printf("f %p, r %p, fnext %p, rnext %p\n", q.front, q.rear, q.front->next, q.rear->next);
    traverse(&q);

    out_queue(&q, &val);
    printf("f %p, r %p, fnext %p, rnext %p\n", q.front, q.rear, q.front->next, q.rear->next);
    traverse(&q);
    out_queue(&q, &val);
    printf("f %p, r %p, fnext %p, rnext %p\n", q.front, q.rear, q.front->next, q.rear->next);
    out_queue(&q, &val);
    printf("f %p, r %p, fnext %p, rnext %p\n", q.front, q.rear, q.front->next, q.rear->next);
    traverse(&q);

    en_queue(&q, 31);
    printf("f %p, r %p, fnext %p, rnext %p\n", q.front, q.rear, q.front->next, q.rear->next);
    traverse(&q);
    en_queue(&q, 32);
    en_queue(&q, 33);
    traverse(&q);

    clear(&q);
    traverse(&q);

    return 0;
}


output

[root@8be225462e66 c]# gcc queue_link.c && ./a.out
f 0x1b7f2a0, r 0x1b7f2a0, fnext (nil), rnext (nil)
traverse: queue empty!
out_queue... failed, queue empty!
en_queue 21 success.
f 0x1b7f2a0, r 0x1b7f6d0, fnext 0x1b7f6d0, rnext (nil)
en_queue 22 success.
f 0x1b7f2a0, r 0x1b7f6f0, fnext 0x1b7f6d0, rnext (nil)
en_queue 23 success.
f 0x1b7f2a0, r 0x1b7f710, fnext 0x1b7f6d0, rnext (nil)
traverse: 21 22 23
out_queue...success, value: 21
f 0x1b7f2a0, r 0x1b7f710, fnext 0x1b7f6f0, rnext (nil)
traverse: 22 23
out_queue...success, value: 22
f 0x1b7f2a0, r 0x1b7f710, fnext 0x1b7f710, rnext (nil)
out_queue...success, value: 23
f 0x1b7f2a0, r 0x1b7f2a0, fnext (nil), rnext (nil)
traverse: queue empty!
en_queue 31 success.
f 0x1b7f2a0, r 0x1b7f710, fnext 0x1b7f710, rnext (nil)
traverse: 31
en_queue 32 success.
en_queue 33 success.
traverse: 31 32 33
clear...
traverse: queue empty!
[root@8be225462e66 c]#