从单链表中删除节点

时间:2011-02-27 22:44:29

标签: c data-structures linked-list

我需要从单链表中删除节点。我知道这是一件很简单的事情,但我的想法是空白的,我搜索了谷歌和Stackoverflow,但我真的没有找到任何可以帮助我的东西。

基本上节点列表包含在桶中;像这样:

struct node{
  unsigned char id[20];
  struct node *next;
};

struct bucket{
  unsigned char id;
  struct node *nodes;
};

我有一个功能

struct bucket *dht_bucketfind(unsigned char *id);  // return bucket with id[20]

找到正确的水桶。所以我知道如何找到正确的存储桶,但我不知道如何删除给定的节点。我想通过nodeid删除节点(我想,我还没有真正编写将调用remove函数的代码;)但我认为如果有必要,我将能够修改代码。我认为这就是解决这个问题所需要的一切。提前谢谢。

8 个答案:

答案 0 :(得分:2)

如果您知道要删除的项目,则必须执行以下两项操作:

  1. 更改指向目标项的所有指针,使其指向目标项的next成员。这将是前面项目的next指针,或列表bucket.nodes的头部。
  2. 释放您刚刚无法访问的节点。
  3. 一旦你理解了你在做什么,操作链表的代码真的不是那么棘手。

答案 1 :(得分:2)

您的节点除了id之外没有任何有效负载,因此,根据节点的数据有效负载,您可能实际上不需要以标准方式迭代列表。如果删除者只知道他们想要删除的节点的地址,这将非常有用。

如果您的有效负载是指向其他数据的指针:

struct _node {
     void *data;
     unsigned char id[20];
     struct _node *next
}

然后你可以通过窃取下一个节点的有效负载来“删除”一个节点,然后脱钩下一个节点:

int delete (struct _node *node)
{
     struct _node *temp;

     memcpy(node->id, node->next->id, 20);
     free_function(node->data);
     node->data = node->next->data;

     temp = node->next;
     node->next = node->next->next);
     free(temp);

     return 0;
 }

答案 2 :(得分:1)

/* define your two pointers, prev and cur */
prev=NULL;
cur=head;
/* traverse the list until you find your target */
while (cur != NULL && cur->id != search_id) {
  prev=cur;
  cur=cur->next;
}
/* if a result is found */
if (cur != NULL) {
  /* check for the head of the list */
  if (prev == NULL)
    head=cur->next;
  else
    prev->next=cur->next;
  /* release the old memory structure */
  free(cur);
}

答案 3 :(得分:1)

public void Remove(T data)
{
    if (this.Head.Data.Equals(data))
    {
        this.Head = this.Head.Next;
        this.Count = this.Count - 1;
    }
    else
    {
        LinkedListNode<T> node = this.Head;
        bool found = false;
        while (node.Next != null && !found)
        {
            if (node.Next.Data.Equals(data))
            {
                found = true;
                node.Next = node.Next.Next;
                this.Count = Count - 1;
            }
            else
            {
                node = node.Next;
            }
        }
    }
}

答案 4 :(得分:0)

自从我与C合作以来,它已经很久了,但这应该是编译干净的。

基本上,您需要在迭代链表时跟踪前一个指针。当您找到要删除的节点时,只需更改上一个指针即可跳过删除节点。

此函数删除所有具有id(find)的节点。如果只想删除第一个匹配项,则在自由语句后面添加一个返回值。

void delete(struct bucket *thisBucket, unsigned char find[20]) {
  struct node *prev = null;
  struct node *curr = thisBucket->nodes;

  while (curr != null) {
    if (!strcmp(curr->id, find)) { // found the node?
      if (prev == null) { // going to delete the first node (header)?
        thisBucket->nodes = curr->next;  // set the new header to the second node
      } else {
        prev->next = curr->next;
      }
      free(curr);

      // if deleted the first node, then current is now the new header,
      // else jump to the next
      curr = prev == null? thisBucket->nodes : prev->next;

    } else { // not found, keep going
      prev = curr;
      curr = curr->next;
    }
  }
}

答案 5 :(得分:0)

以下内容不包含任何错误检查,仅从列表中删除当前节点...

pPrev->next = pCurrent->next;

您的偏好可能会有所不同,但我倾向于将我的链表节点放在结构的开头(只要可行)。

struct node{
  struct node *next;
  unsigned char id[20];
};

struct bucket{
  struct node *nodes;
  unsigned char id;
};

我发现这通常有助于简化指针算法,并在需要时允许简单的类型转换。

答案 6 :(得分:0)

这将删除给定其地址的节点;您可以修改它以删除给定其id的节点,但是您没有指定id的形式 - 它是NUL终止的字符串,还是20字节?

// remove node from bucket and return true
// or return false if node isn't in bucket
int dht_rmnode(struct bucket* bucket, struct node* node)
{
    struct node** ppnode = &bucket->nodes;
    for( ;; ){
        struct node* pnode = *ppnode;
        if( pnode == NULL ) return 0;

        if( pnode == node ){
            *ppnode = pnode->next;
            return 1;
        }
        ppnode = &pnode->next;
    }
}

或者,更紧凑,

// remove node from bucket and return true
// or return false if node isn't in bucket
int dht_rmnode(struct bucket* bucket, struct node* node)
{
    struct node** ppnode = &bucket->nodes;
    struct node* pnode;
    for( ; (pnode = *ppnode); ppnode = &pnode->next )
        if( pnode == node ){
            *ppnode = pnode->next;
            return 1;
        }

    return 0;
}

答案 7 :(得分:0)

typedef struct node
{
int id;
struct node* next;
}Node;
void delete_element(void)
{
int i;
Node* current=head;
Node* brev=NULL;

if(i==head->id){
head=current->next;
free(current);}
else{
while(NULL!=current->next)
    {
        if(i==current->next->id){
        brev=current;
        current=current->next;
        break;}
        else
        current=current->next;
    }
if(i==current->id)
    {
        if(NULL==head->next){
        head=NULL;
        free(current);}
        else
        brev->next=current->next;
        free(current);
    }
else
    printf("this id does not exist\n");
}
}