所以我正在阅读一本教科书示例,说明如何从C中的链表创建队列,而且我有点卡在一段代码的工作原理上。
因此,教科书使用的示例是一个队列,可以帮助模拟排队的乘客为票务代理提供服务。
他们首先定义了如何实现队列的结构:
/* Insert typedef for queue_element_t */
typedef struct queue_node_s {
queue_element_t element;
struct queue_node_s *restp;
} queue_node_t;
typedef struct {
queue_node_t *frontp,
*rearp;
int size;
} queue_t;
然后他们继续展示两个功能的实现:
void add_to_q(queue_t *qp, queue_element_t ele);
queue_element_t remove_from_q(queue_t *qp);
第一个函数定义为:
/*
* Adds ele at the end of queue accessed through qp
* Pre: queue is not empty
*/
void
add_to_q(queue_t *qp, /* input/output - queue */
queue_element_t ele) /* input - element to add */
{
if (qp->size == 0) { /* adds to empty queue */
qp->rearp = (queue_node_t *)malloc(sizeof (queue_node_t));
qp->frontp = qp->rearp;
} else { /* adds to non-empty queue */
qp->rearp->restp =
(queue_node_t *)malloc(sizeof (queue_node_t));
qp->rearp = qp->rearp->restp;
}
qp->rearp->element = ele; /* defines newly added node */
qp->rearp->restp = NULL;
++(qp->size);
}
类似地,remove_from_q以下列方式实现:
/*
* Removes and frees first node of queue, returning value stored there.
* Pre: queue is not empty
*/
queue_element_t
remove_from_q(queue_t *qp) /* input/output - queue */
{
queue_node_t *to_freep; /* pointer to node removed */
queue_element_t ans; /* initial queue value which is to
be returned */
to_freep = qp->frontp; /* saves pointer to node being
deleted */
ans = to_freep->element; /* retrieves value to return */
qp->frontp = to_freep->restp; /* deletes first node */
free(to_freep); /* deallocates space */
--(qp->size);
if (qp->size == 0) /* queue's ONLY node was deleted */
qp->rearp = NULL;
return (ans);
}
当我自己完成它时,我发现我仍然有点困惑为什么它这样工作?如果我错了,请纠正我:在第一次调用函数add_to_q时,我们假设队列最初为空,因此queue_node_t指针frontp和rearp都指向堆中分配的内存中的相同位置。因此,frontp-> restp == rearp-> restp,这就是你被允许写行的原因
qp->frontp = to_freep->restp;
在remove_from_q?另外,在第二次调用add_to_q时,当你将第二个元素前端点添加到同一个内存中时,后面会移动到一个新位置吗?
我的后续工作是,一旦一个元素进入队列,如果我们去添加一个新成员到队列的后面,下面的代码块如何为我们提供我们期望的正确功能我们的队列?:
else { /* adds to non-empty queue */
qp->rearp->restp =
(queue_node_t *)malloc(sizeof (queue_node_t));
qp->rearp = qp->rearp->restp;
}
qp->rearp->element = ele; /* defines newly added node */
qp->rearp->restp = NULL;
++(qp->size);
}
我已经尝试用内存块来解决这个问题,但是我不知道一旦程序到达行qp->rearp = qp->rearp->restp;
,当你写qp->rearp->restp = NULL;
它没有&{ #39; t还设置qp-> rearp等于NULL,因为它们应该(据我所知)指向内存中的相同位置。
任何指导都将不胜感激!!! 谢谢:))
答案 0 :(得分:2)
让我们简要介绍一下:
队列是线性数据结构,其中第一个元素从一端插入,名为 REAR ,并且删除现有元素来自另一端称为 FRONT 。
KeyPoint:将元素添加到队列中的过程称为Enqueue(插入),从队列中删除元素的过程称为Dequeue(删除)。
现在,我已经创建了两个设计,让您了解插入和删除的基本概念。
<强> 1。插入(也是创建)
<强> 2。在队列中删除:
我希望你能理解使用链表的队列的基本概念,这样你以后就不会混淆,可以进一步学习。
答案 1 :(得分:0)
队列是先进先出结构(我想你已经知道了)。此特定代码使用链接列表实现它。它基本上做的是每当你排队&#34;您将一些数据添加到链表的后端(尾部)。因此,rear
会在add_to_q
的每次调用中被修改。
我的后续工作是,一旦一个元素进入队列,如果我们去添加一个新成员到队列的后面,下面的代码块如何为我们提供我们期望的正确功能我们的队列?:
qp->rearp
指向最后一个节点(代码的后面)。 qp->rearp->restp
是所谓的&#34; next&#34;该节点的指针。 qp->rearp->restp=malloc...
在&#34; next&#34;处创建一个新节点旧的后方。 qp->rearp=qp->rearp->restp
使qp->rearp
指向新的后方。 qp->rearp->restp
使&#34; next&#34;最后一个节点NULL
。
因此,代码基本上在链表的尾端添加新节点,并从头端删除节点(反过来应该更高效)。他们正在使用&#34; rearp&#34;因为你应该站在&#34;后面&#34;队列。
这基本上是在处理链接列表的同时保持&#34;尾部&#34;指针以及&#34; head&#34;用于提高效率的指针。
答案 2 :(得分:0)
我建议用块和指针再次(再次)绘制它。首先,请确保您了解仅使用头部和下一个指针的简单链接列表。然后进入保持头部,尾部和尺寸信息的那个。你的评论实际上听起来像是你大部分都得到了它,直到最后一条关于将最后一个元素设置为下一个指针为NULL的评论。 (提示:qp-&gt; rearp现在是我们的最后一个节点,我们将元素放入其中,并将它的'next'指针设置为NULL)