学习线性表,高深又烧脑?莫怕,手把手教你终结烦恼!(队列:链式存储结构)

经过长途跋涉,队列的顺序存储结构总算告一段落。今天我们要用链表来实现队列。队列中只允许在单链表的表头进行出队操作,在表尾进行插入操作,因此需要使用队头front和队尾rear两个指针,用front指向队首结点,用rear指向队尾结点。和链栈一样,链队列也不考虑队满溢出的情况。

对于链队列的声明,首先我们要像单链表一样声明一下数据结点:

typedef struct node{
    ElemType data;
    struct node* next;
}DataNode;

由于队列的特殊性,我们还需要两个指针front、rear,分别指向首结点和尾结点。因此,我们需要单独声明一个结点,将front、rear放在一起:

typedef struct{
    DataNode* front;
    DataNode* rear;
}LinkQueue;

链队列的示意图如下:

队列的基本算法如下所示:仍然是一如既往地使用带头结点的做法,只不过队列的操作相比于栈,稍微复杂了一些。首先,在声明结点的时候,我们声明了两个,在链队列结点里面还嵌套了指向数据结点的两个指针,在这里可能会有一些绕,不过画图的话还是比较清楚的。还有就是出队的后如果队列空了,一定要让front=rear,使它满足队列空的条件,不然的话,会和其它的操作(比如判断队列是否为空)不兼容,导致出错。

下面看一下代码(我写完之后花了不少精力找错误):

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef char ElemType;
typedef struct node{
    ElemType data;
    struct node* next;
}DataNode;
typedef struct{
    DataNode* front;
    DataNode* rear;
}LinkQueue;
LinkQueue* Initqueue(LinkQueue* q){//初始化队列。
    q=(LinkQueue*)malloc(sizeof(LinkQueue));//为链队列结点分配内存空间。
    q->front=(DataNode*)malloc(sizeof(DataNode));//为数据结点分配内存空间。
    q->rear=q->front;//将链表置为空。
    return q;
}
void DestroyQueue(LinkQueue* q){//销毁队列。
    DataNode* pre=q->front->next,*p;//使用前驱结点pre和后继结点p组合删除所有元素。
    if(pre!=NULL){//当pre不为空时,p结点为其后继结点。
        p=pre->next;
        while(p){//当p不为空时,边删除,指针边后移。
            free(pre);
            pre=p;
            p=pre->next;
        }
        free(pre);//释放掉队列中仅剩的最后一个数据结点。
    }
    free(q);//释放掉队列节点。
}
bool QueueEmpty(LinkQueue* q){//判断队列是否为空。
    return q->rear==q->front;
}
void enQueue(LinkQueue* q,ElemType e){//入队。
    DataNode* p;
    p=(DataNode*)malloc(sizeof(DataNode));//为新添加的数据结点分配内存空间。
    p->data=e;//新元素加入数据节点。
    p->next=NULL;//新加入结点的next域设为NULL,不然在销毁结点的时候判空操作会出问题。
    q->rear->next=p;//结点插入到队列末尾。
    q->rear=p;//rear指针指向最后一个结点。
}
bool deQueue(LinkQueue* q,ElemType *e){//出队。
    DataNode *t;//用来保存将要被删除的结点。
    if(q->rear==q->front)return false;//如果队空,则不能进行删除操作。
    t=q->front->next;//保存要被删除的结点。
    q->front->next=t->next;//删除结点。
    if(q->rear==t)//如果队列中只有这一个元素,则将队列置空。
        q->rear=q->front;
    *e=t->data;//取出被删除的元素。
    free(t);//释放掉被删除节点的空间。
    return true;
}

大多数知识还是前面学过的基操,只不过在队列里面需要大家有一点举一反三的能力。细节决定成败,有些东西虽然看起来简单,但是做起来还是容易考虑不周全。不就是线性表吗?多简单?我都写了一万遍了怎么可能还出错?是很简单,但是越简单的东西越容易疏忽大意,所以在实践的时候一定要眼观四路,耳听八方,才有可能把错误率降到最低。今天就说这么多,欢迎大家留言交流!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值