【问题标题】:Insertion into a Linked list using double pointer in C在C中使用双指针插入链接列表
【发布时间】:2016-04-11 16:23:50
【问题描述】:
void insert(list **l, int x)
{
       list *p;
       p = malloc(sizeof(list));
       p->item = x;
       p->next = *l;
       *l=p;
}

为什么我们使用双指针?我们能用单指针做同样的事情吗?我在《算法设计手册》第 69 页第 2 版一书中看到了这个例子。

列表基本上是节点,仅供参考。

【问题讨论】:

  • 这会将新节点添加到列表中(实际上是一个堆栈)。 调用者需要以某种方式获取指向新列表头的指针。这是做到这一点的一种方法。另一个是让函数始终返回列表头。

标签: c algorithm linked-list


【解决方案1】:

我们可以用单指针做同样的事情吗?

您可以使用带有少量更新的单个指针来完成此操作。

返回已分配的指针,并确保函数调用已适当更改。

list* insert(list *l, int x)
{
   // list = *p
   // What was that? That is not valid code.

   list* p = malloc(sizeof(list));
   p->item = x;
   p->next = l;
   return p;
}

并将其用作

list* l = NULL;
l = insert(l, 10);

【讨论】:

    【解决方案2】:

    C 中的参数是按值传递的。因此,为了对函数中的变量进行一些更改,我们必须告诉该函数变量的地址。这使它能够通过将数据写入相应的内存来间接更改变量的值。

    因此,要修改int,您必须传递int *。在您的情况下,要修改 list *(p->next 的类型),您必须传递 list **。

    【讨论】:

      【解决方案3】:

      这里使用双指针是合理的,因为在函数中你在列表的头部插入节点,所以变量l将被新的头部*l=p;改变

      *l->|node1|->|node2| //initial value
      p->|nodeP| //after p = malloc(sizeof(list)); p->item = x;
      p->|nodeP|->|node1|->|node2| //p->next = *l;
      *l->|nodeP|->|node1|->|node2| //after *l=p
      

      在这种情况下,函数是这样调用的:

      list *head;
      insert(&head, 4);
      

      对于您的问题:

      我们可以用单指针做同样的事情吗?

      是的,函数将如下所示:

      list *insert(list *l, int x)
      {
             list *p;
             p = malloc(sizeof(list));
             p->item = x;
             p->next = l;
             return p;
      }
      

      在这种情况下你可以像这样调用函数:

      list *head;
      head = insert(head, 4);
      

      【讨论】:

        【解决方案4】:
        Basically u might be calling the insert function using insert(&head,x);
        Previously head would have stored the address of your first node in the
        linked list and u give the address of the head node to l and to access the
        address of a u need to dereference it once and to change its value u need to 
        dereference it twice.
        
        and obviously u can do it without double pointers just giving the value of   
        head to l  insert(head,x)....and in the function declaring insert(int *l,int 
        x) 
        suppose
        
        address of a(first node)=123
        
        value of head=123
        
        address of head =456
        
        l(storing address of head)=456
        
        In order to get the address of the first node dereference once
        
        *l=123
        in order to change value or to go to the next node you dereference it twice
        for visual satisfaction have a look at the diagram image i tried to figure
        out for your better understanding.
        
        
        ----------
        

        [这是一个图表,可以让您清楚地了解双指针是如何实现的
        在这里工作][1] [1]:http://i.stack.imgur.com/HQOaa.jpg

        【讨论】:

          【解决方案5】:

          您需要在此示例中使用双指针,因为您还想更改列表的起始节点。所以基本上当你插入一个新元素时,你还想让包含它的节点成为列表的第一个。如果您只传递一个指针(list *l)并将新创建的节点(p)分配给它,则更改(我所说的更改是指它将成为列表的第一个节点的事实)只会在您的函数内部可用,并且不会在函数外部传播。

          为了更清楚地说明,如果您接收一个简单的指针 (list *l),那么您基本上是在将位于函数外部的 list* 变量存储的地址复制到新创建的指针中( l 参数)。因此,函数内部的l 变量是一个不同的指针(与函数外部的指针变量相比,内存中的位置不同)包含与函数外部指针相同的地址。所以这就是为什么将新创建的元素分配给这个l 单指针只会使新插入的元素成为第一个唯一的本地(函数范围)。

          与接收双指针时的替代方法(所以list **l)相比,真正发生的是通过将外部指针变量传递给函数,您实际上是在传递外部指针的地址,不要与指针所包含的地址相混淆。 (小心,因为您必须像这样调用函数:insert(&l, 2))。这样,您仍然可以通过取消引用外部指针并将其用作右值 (p->next = *l) 来获得外部指针所包含的地址,同时您还拥有外部变量的地址,因此当您制作 *l = p (注意*l 在这里用作左值),您实际上是在取消引用双指针,因此您将获得真实变量(外部变量)的地址,并将新创建的节点分配给它。换句话说,您实际上是将新创建的节点设置为起始节点,但这次也在函数之外。

          真的希望这不是非常混乱。

          【讨论】:

            猜你喜欢
            • 2019-04-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-02
            • 1970-01-01
            • 1970-01-01
            • 2012-04-20
            • 2020-07-06
            相关资源
            最近更新 更多