C语言回顾17-队列
队列也是一种需要我们掌握的数据结构,它最大的特点是先进先出,从队头进从队尾出。那我们可以考虑一下要如何实现呢?我们在构建栈的时候使用看了头插法,这样子可以实现先入后出,因为最后插入的都在最前面,所以可以实现后入先出。那么我们要实现先进先出就需要在队尾插入元素,这样子每次出的就是之前更早进入的元素,可以看看下面的图示:
我们接下来再具体说明每一步的代码实现:
-
创建节点
和链表栈一样,我们同样需要用结构体来表示节点,实现队列,这个节点但是因为队列需要队头和队尾,我们把队头和队尾指针再存放到一个结构体里,这样子比较方便使用,也就是说,队列的主题还是使用一个类型的结构体链接起来,和链表类似,只是我们可以通过结构体把队头队尾存储起来:
typedef struct info
{
int num;
struct info*next;
}Queue;
struct data
{
Queue*top;
Queue*rear;
}Q;
这样我们就构建好了所需要的节点类型,以及队头队尾,下面在看具体如何使用
- 队列初始化
在开始使用队列的时候,和链表一样需要一些准备工作,我们可以想想,首先我们需要初始化每一个节点,给他们申请内存以及节点赋空,在队列里还有一点不一样,因为我们需要采用尾插法,那么我们需要用队尾来储存每一次插入后的尾节点,那么开始的时候我们就需要让队头队尾相等,然后在插入的时候从队尾插入,每次移动队尾就可以了,我们先来看看准备工作。
void QueueInt(Queue*p)
{
p=(Queue*)malloc(sizeof(Queue));
p->next=NULL;
}
void IntQueue()
{
QueueInt(Q.rear);
QueueInt(Q.top);
Q.rear=Q.top;
}
通过这样两个函数,我们可以实现内存的分配,以及队头队尾的初始化, 现在队列的情况是这样的然后我们每次把节点链接到队尾后面,并且把队尾移动到尾节点的位置就可以实现队列的插入。
- 入队
队列的重点就在于他的插入方法,和栈的头插法不同,队列需要在队尾插入元素,但是队尾不像队头不动,每次插入后队尾都会改变,如果采用遍历的方法到达队尾太浪费时间,于是我们使用队尾指针来保存队尾的位置,每一次只需要在队尾插入,并且插入结束后队尾再次储存新的队尾,实现队列的插入:
void Inqueue(int n)
{
Queue*p;
QueueInt(p);
p->num=n;
Q.rear->next=p;
Q.rear=p;
}
这个函数就可以实现队列的插入,并且插入结束后,Q.rear指向了这个新插入的节点也就是新的队尾。后面我们再次插入的时候就需要从这个新的尾节点开始。
- 出队
现在我们来实现出队,出队很简单,只需要头指针往后移动就行,但是我们需要判断队列是否为空,也就是队头是否等于队尾,如果不为空,那么我们就弹出队头元素,并将那一块内存释放,这个操作和链表,栈的操作很相似,下面我们来编程实现:
void DeQueue()
{
Queue *p=Q->top->next;
if(Q->top->next==Q->rear)
{
printf("队空\n");
}
else
{
printf("%d",p->num);
Q->top.next=p->next;
free(p);
}
}
在这个函数里面,我们就先判断了队列是否为空,然后如果不为空,我们用指针p指向要弹出的元素,也就是队头的第一个元素,然后我们需要free掉p所指的内存,也就是刚才用来存放数据的内存,我们已经弹出了这块数据,所以需要把这块内存也释放掉,这样子我们就完整的实现了队列的队头元素的弹出,并且在队列为空的时候不会再继续弹出元素。
队列的基本上实现和一些基本原理就是这样了,这是我们学的比较重要的几个数据结构,需要熟练掌握,灵活运用,多多尝试。
21 : 40