数据结构之链队列(c语言实现)

队列的链式存储——链队列

话说链栈有一个栈顶指针;而队列和栈是有差别的,队列只能一头进另一头出,而链队列的进出口都有警卫把守,分别是队头指针(front)大哥和队尾指针(rear)小弟,有的剧情会是这样:大哥躺在椅子上小弟帮大哥办事,那么这头指针大哥就是在队的头部始终不动,稳如狗,而尾指针小弟就随着队列有元素入队,尾指针就要往右移动。小弟都是这样,再累也不怕。

来看一看大哥和小弟的生活图

在这里插入图片描述

言归正传,链队列的结构体定义,和链栈很相似,链队列定义了要移动的队尾指针和不动的队头指针;链表的头节点作为链队列的空队。

typedef struct QNode
{
    ElemType data;
    struct QNode *next;
}QNode, *QueueN;

typedef struct
{
    QueueN Front;   //This queue head pointer
    QueueN Rear;      //This queue tail pointer
}LinkQueue;

关于链队列的入队和出队看下图

在这里插入图片描述

代码部分

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

typedef char ElemType;

typedef struct QNode
{
    ElemType data;
    struct QNode *next;
}QNode, *QueueN;

typedef struct
{
    QueueN Front;   //This queue head pointer
    QueueN Rear;      //This queue tail pointer
}LinkQueue;

void init_Queue(LinkQueue *Q)
{
    Q->Front = (QueueN)malloc(sizeof(QNode));
    if (!Q->Front)
    {
        printf("The memory allocation failed !\n");
        return;
    }
    Q->Rear = Q->Front;
    Q->Front->next = NULL;
}

void print_Queue(LinkQueue Q)
{
    if (Q.Front == Q.Rear)
    {
        printf("The queue is empty!\n");
        return;
    }
    Q.Front = Q.Front->next;
    while(Q.Front)
    {
        printf(" %c ", Q.Front->data);
        Q.Front = Q.Front->next;
    }
    printf("\n");
}

void EnQueue(LinkQueue *Q, ElemType e)
{
    QueueN qNew = (QueueN)malloc(sizeof(QNode));
    if (!qNew)
    {
        printf("The memory allocation failed !\n");
        return;
    }
    qNew->data = e;
    qNew->next = NULL;
    Q->Rear->next = qNew;
    Q->Rear = qNew;
}

bool DeQueue(LinkQueue *Q, ElemType *e)
{
    QueueN p;
    if (Q->Front == Q->Rear)
    {
        printf("The queue is empty!\n");
        return false;
    }
    p = Q->Front->next;
    *e = p->data;
    Q->Front->next = p->next;
    if (Q->Rear == p)
    {
        Q->Rear = Q->Front;
    }
    free(p);
    return true;
}

int length_Queue(LinkQueue Q)
{
    int len = 0;
    if (Q.Front == Q.Rear)
    {
        printf("The queue is empty! ");
        return len;
    }
    else
    {
        Q.Front = Q.Front->next;
        while(Q.Front)
        {
            ++len;
            Q.Front = Q.Front->next;
        }
        return len;
    }
}

bool clear_Queue(LinkQueue *Q)
{
    if (Q->Front == Q->Rear)
    {
        return true;
    }
    QueueN q;
    QueueN p;
    q = Q->Front->next;
    while(q)
    {
        p = q->next;
        free(q);
        q = p;
    }
    Q->Front->next = NULL;
    Q->Rear = Q->Front;
    return true;
}

bool destroy_Queue(LinkQueue *Q)
{
    clear_Queue(Q);
    free(Q->Front);
    Q->Front = NULL;
    Q->Rear = NULL;
    Q = NULL;
    return true;
}

int main()
{
    LinkQueue Q;
    init_Queue(&Q);    //Initialization queue
    int option = 1;
    ElemType e;
    int len = 0;
    printf("\n 1. Initialization queue\n 2. Traverse queue\n 3. Enqueue\n 4. Dequeue\n 5. Queue`s length\n 6. Clear queue\n 7. Destroy queue\n 0. Exit\n");
    while(option)
    {
        printf("Please operate on the queue: ");
        scanf("%d", &option);

        switch(option)
        {
        case 1:
            init_Queue(&Q);
            break;

        case 2:
            //Print the queue of all elements
            print_Queue(Q);
            break;

        case 3:
            getchar();
            printf("Please enter the element to be enqueued: ");
            scanf("%c", &e);
            //Enqueue opertion of the queue
            EnQueue(&Q, e);
            break;

        case 4:
            getchar();
            //Dequeue opertion of the queue
            if (DeQueue(&Q, &e))
            {
                printf("The element to be dequeued is %c\n", e);
            }
            else
            {
                printf("Dequeue is fail !\n");
            }
            break;

        case 5:
            //Calculate the length of the queue
            len = length_Queue(Q);
            printf("The queue`s length is %d\n", len);
            break;

        case 6:
            //Clear the queue
            if (clear_Queue(&Q))
            {
                printf("The queue has been cleared!\n");
            }
            break;

        case 7:
            //Destroy the queue
            if (destroy_Queue(&Q))
            {
                printf("The queue has been destroy!\n");
            }
            break;

        case 0:
            exit(0);

        default:
            printf("Incorrect operation! Please re-operate!\n");
            break;
        }

        scanf("%*[^\n]%*c");
        option = 9;
    }
    return 0;
}

如果确定队列的长度,那么用循环队列更方便;否则,更适合用链队列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值