使用指向指针删除结构节点

时间:2018-02-25 16:20:57

标签: c

假设我有一个链表,下一个函数从链表中删除结构节点

struct list **lpp;
for (lpp = &list; *lpp != NULL; lpp = &(*lpp)->next)
{
    if ((*lpp)->item == i)
    {
        *lpp = (*lpp)->next;
        break;
    }
}

请解释一下:

  
      
  1. lpp =&(* lpp) - >接下来,我可以把它写成lpp = lpp->接下来,这不一样吗?
  2.   
  3. * lpp =(* lpp) - > next
  4.   

底线,我没看到这个函数如何从列表中删除结构节点

1 个答案:

答案 0 :(得分:0)

您的代码是极其简化且不完整的节点删除尝试 你必须处理边缘情况以及实际上free内存。

这一行:

 *lpp = (*lpp)->next;

负责列表中的taking out节点。  它仅在*lpp是列表头并且列表中有另一个元素时才有效。  *lpp指向您不再需要的节点,它将被列表中的下一个节点替换

 (*lpp)->next;
  

lpp = &(*lpp)->next,我可以将其写为lpp = lpp->next,这不是   一样吗?

不,不是。并且lpp = lpp->next将无法编译。

&是一个解除引用运算符。它正在获取节点指针的地址。 您可以将此行写为

lpp = & ( (*lpp)->next ); 

,您可以将(*lpp)->next识别为列表中的下一个节点指针。

lpp是指向指针的指针。 *lpp->next是编译器已知的表达式,而不是lpp->next

我猜你误会了 lpp = & ( (*lpp)->next );

作为

lpp = &* (lpp->next); 

并认为&*会自行取消。

如果要删除列表中间的节点,则必须连接  在要删除的节点之前存在的节点,该节点位于标记为删除的节点之后的节点。

类似于:

         prev = current;                       
         to_free = current->next;         // node to be freed  

         prev->next = to_free->next;      // connect nodes before deletion        
         free(to_free)
  

是否可以向我展示如何使用删除链接列表节点   双重的poniters? - Fela93

我添加了节点删除的测试程序:

#include <stdio.h>
#include <stdlib.h>

// Basic simple single list implementation to illustrate 
// a proper deletion of the node which has a specfic data value.

// Node in List
typedef struct node {
    int data;
    struct node* next; // pointer to next node
}node;

// returns newly created node
node* node_new(int data)
{
    node* new_node = malloc(sizeof(node)); // allocate memory for the node 

    if (new_node == NULL)
        return NULL;                             // protection 

    new_node->data = data;                       // remember the data 
    new_node->next = NULL;                       // no next node

    return new_node;                             // return new created node
}

// The method creates a node and prepends it at the beginning of the list.
// 
// Frequently used names for this method:
// 
// insert at head
// add first
// prepend
//
// returns new head or NULL on failer

node* add_node(node **head, node* new_node)

{
   // Add item to the front of the in_list, return pointer to the prepended node (head)    

    if(head == NULL)
        return NULL;

    if(new_node == NULL)                         // problem, not enough memory
       return NULL;                              // in_list->head has not changed 

/* 
                 new_node      
                   |*| -->  NULL   
                   next        
*/       
    if(*head == NULL)                    // if list is empty 
    {
        *head = new_node;                // the new_node becomes a head   
    }
    else // list already have a head node
    {
/*
                |2|-->|1|-->NULL
                 ^ 
                 |
                 *
                head (2) (list pointer)
*/
        new_node->next = *head;         // now, the new node next pointer points to the node pointed by the list head, see below:       
/* 
          new_node     
            |3|-->     |2|-->|1|-->NULL
                        ^  
                        |
                        *
                       head (list pointer)
*/          
        *head = new_node;               // the list head has to move to new_node ( a new prepanded node)  
 /* 
          new_node       
            |3|-->  |2|-->|1|-->NULL
             ^       
             |           
             *           
            head (3) (list pointer)
*/         
    }
    return *head;                       // we are returning pinter to new_node
}

// Print out list
void print_nodes(node** head)
{
    node* node;

    if (head == NULL) {
        return;
    }

    if (*head == NULL){
        printf("List is empty!\n");
        return;
    }

    printf("List: ");
    node = *head;

    while(node != NULL)
    {
        printf(" %d", node->data);

        node = node->next;
    }

    printf("\n");
}

struct node *find(struct node *start, int data)             // find p to be removed
{
    node* node;

    if (start == NULL)
        return NULL;

    node = start;

    while(node != NULL)
    {
        if (node->data == data)
            return node; 

        node = node->next;
    }

    return NULL;
}

int delete(struct node **start, int data)
{
     struct node *p, *prev, *next, *to_free;

     if (start == NULL)                      // protection
        return 0;

     p = find(*start, data);                 // find element to be removed

     if (p == NULL)
        return 0;

     if (*start == NULL)
        return 0;                            // protection

     if(*start == p)                         // head == p
     {
        if((*start)->next !=NULL)
        {
            *start = (*start)->next;         // move head

            printf("Will be removed: %p\n",p);        
            free(p);                         // remove old head

            return 1;
        }
        else // the only node
        {
            free(p);                        // free the node pointed by *start (header)

            printf("Last node removed\n");
            *start = NULL;                  // header points to NULL 

            return 1;
        }
     }

     // p != start:

     next = *start; 
     while (next != NULL)
     {
        prev = next;                       
        to_free = next->next;                // candidate to be freed   

       if( to_free == p )
        {
            prev->next = to_free->next;      // connect nodes before deletion 

            free(to_free);                   // now free the remembered `next`
            to_free = NULL;                  // so it does not point to the released memory
            return 1;
        }

        next = next->next;                   // this node was not a match 
     } //while

    return 0; 
}

int main() {   
   node *head = NULL; 

   printf("head: %p\n", head);

   node *n1 = node_new(1);
   node *n2 = node_new(2);
   node *n3 = node_new(3);

   print_nodes(&head);

   add_node(&head, n1);
   add_node(&head, n2);
   add_node(&head, n3);

   printf("head points to:  %p\n", head);

  // list has 3 elements
   print_nodes(&head);

   delete(&head, 3);  
   print_nodes(&head);

   delete(&head, 1);  
   print_nodes(&head);

   delete(&head, 2);
   print_nodes(&head);

   printf("head points to: %p\n", head);

   print_nodes(&head);

  return 0;
}

输出:

head: (nil)
List is empty!
head points to:  0x5617cd3802b0
List:  3 2 1
Will be removed: 0x5617cd3802b0
List:  2 1
List:  2
Last node removed
List is empty!
head points to: (nil)
List is empty!