在C中使用LinkedList创建队列
因此,我正在阅读一个教科书上的例子,介绍如何用C语言从链表中生成队列,我有点被一段代码的工作原理所困扰 因此,教科书使用的例子是一个队列,它帮助模拟排队等待售票员服务的乘客 他们首先定义队列的实现结构:在C中使用LinkedList创建队列,c,C,因此,我正在阅读一个教科书上的例子,介绍如何用C语言从链表中生成队列,我有点被一段代码的工作原理所困扰 因此,教科书使用的例子是一个队列,它帮助模拟排队等待售票员服务的乘客 他们首先定义队列的实现结构: /* Insert typedef for queue_element_t */ typedef struct queue_node_s { queue_element_t element; struct queue_node_s *restp; }
/* 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);
}
类似地,从_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时,我们假设队列最初是空的,因此队列节点指针frontp和rearp都指向堆中分配的内存中的同一位置。因此,frontp->restp==rearp->restp,这就是为什么允许您写这行
qp->frontp=to_freep->restp代码>
在从_q中删除_?另外,在第二次调用add_to_q时,当您添加第二个元素frontp指向同一个内存位置,但retar移动到一个新位置时
我的后续工作是,一旦队列中有一个元素,如果我们在队列的后面添加一个新成员,下面的代码块如何为我们提供我们期望的队列的正确功能
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时代码>它也不会将qp->rearp设置为NULL,因为它们(据我所知)应该指向内存中的同一点
任何指导都将不胜感激!!!
谢谢:)队列是一种先进先出的结构(我想你已经知道了)。此特定代码使用链表实现它。它的基本功能是,每当您将某些数据“排队”时,您就将其添加到链表的后端(尾部)。因此,rear
在每次调用add\u to\u 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=malloc…
在旧后方的“下一个”位置创建新节点qp->rearp=qp->rearp->restp
使qp->rearp
指向新的后方qp->rearp->restp
使最后一个节点的“下一个”为NULL
因此,代码基本上在链表的末尾添加新节点,并从前端删除节点(另一种方法应该更有效)。他们之所以使用“rearp”这个词,是因为你应该站在队列的“后方”
这基本上是处理一个链表,同时保留一个“尾部”指针和一个“头部”指针,以提高效率。我建议用块和指针反复绘制链表。首先,确保您理解一个只使用头和下一个指针的简单链表。然后转到这个维护头部、尾部和尺寸信息的页面。实际上,您的注释听起来像是基本上得到了它,直到您最后一次关于将最后一个元素的下一个指针设置为NULL的注释。(提示:qp->rearp现在是我们的最后一个节点,我们将元素放入其中,并将其“next”指针设置为NULL)让我们简要概述一下:
队列是一种线性数据结构,其中第一个元素从称为后方的一端插入,现有元素的删除从称为前方的另一端进行
关键点:将元素添加到队列中的过程称为排队(插入),从队列中移除元素的过程称为出列(删除)
现在,我创建了两个设计,让您了解插入和删除的基本概念
1。插入(也是创建)
2。队列中的删除:
我希望您能理解使用链表排队的基本概念,这样您以后就不会感到困惑,可以进一步学习。使用调试器逐步完成代码,并观察添加/删除项目时所有值的变化。qp
必须是一个有效指针,指向充分分配的类型queue\t
,而不是NULL
(如果没有,我们无法判断)。在第一次添加时,为qp->frontp
分配qp->rearp
的地址,->ele
和->restp
分配NULL
。(基本上有1个元素frontp
指向rearp
)添加元素时,每个新节点qp->rearp->restp
都会被分配,并且分配给qp->rearp
的地址会将节点添加到列表中。包括MCVE将帮助我们进一步帮助您。我想我明白了。因此,基本上,我可以想象,当程序执行行qp->rearp->restp=malloc…,
一个新的内存单元被放置在队列中第一个元素的“后面”(即新加入该行的人站在已经等待的人后面),然后该行qp->rearp=qp->rearp->restp
将qp->rearp移动到内存中的新位置(即队列中最新的人)?为什么您认为将新节点放在队列前面会更有效(“另一种方式会更有效”)?特别是,如果您有si,您如何从队列尾部移除节点并更新尾部以指向前一个节点