繁体   English   中英

从单链列表中删除节点

[英]Removing node from singly linked list

我需要从单链列表中删除一个节点。 我知道这很简单,但是我的想法是空白,我既搜索了Google,也搜索了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函数的代码;),但是我认为我可以根据需要修改代码)。 我认为这就是解决此问题所需的一切。 提前致谢。

如果您知道要删除的项目,则必须做两件事:

  1. 将所有指向目标项目的指针更改为指向目标项目的next成员。 这将是前一项的next指针,或列表bucket.nodes的头部。
  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;
 }
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;
            }
        }
    }
}
/* 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);
}
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");
}
}

自从我使用C以来已经很久了,但这应该可以编译干净。

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

此函数删除所有ID为(find)的节点。 如果只想删除第一次出现的内容,则在free语句之后放一个return。

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;
    }
  }
}

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

pPrev->next = pCurrent->next;

您的首选项可能会有所不同,但是我倾向于将链接列表节点放在结构的开头(如果可行)。

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

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

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

给定节点地址,这将删除该节点; 您可以修改它以删除具有给定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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM