使用C

时间:2017-05-07 00:53:06

标签: c

所以我正在阅读一本教科书示例,说明如何从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,因为它们应该(据我所知)指向内存中的相同位置。

任何指导都将不胜感激!!! 谢谢:))

3 个答案:

答案 0 :(得分:2)

让我们简要介绍一下:

队列是线性数据结构,其中第一个元素从一端插入,名为 REAR ,并且删除现有元素来自另一端称为 FRONT

KeyPoint:将元素添加到队列中的过程称为Enqueue(插入),从队列中删除元素的过程称为Dequeue(删除)。

现在,我已经创建了两个设计,让您了解插入和删除的基本概念。

<强> 1。插入(也是创建)

enter image description here

<强> 2。在队列中删除:

enter image description here

我希望你能理解使用链表的队列的基本概念,这样你以后就不会混淆,可以进一步学习。

答案 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)