从单链表中删除节点

发布于 2024-10-19 15:05:48 字数 521 浏览 1 评论 0原文

我需要从单链表中删除一个节点。我知道这是一件简单的事情,但我的大脑一片空白,我搜索了 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 删除节点(我想,我还没有真正编写调用删除函数的代码;)但我想如果有必要我可以修改代码)。我认为这就是解决这个问题所需要的一切。提前致谢。

I need to remove a node from a singly linked list. I know this is a simple thing to do, but my mind is blank and I've searched both Google and Stackoverflow, but I seriously haven't found anything that will help me.

basically the list of nodes is contained in a bucket; like this:

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

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

and I have a function

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

to find the correct bucket. So I know how to find the correct bucket, but I don't know how to remove a given node. I would like to remove the node by nodeid (I think, I haven't really written the code that will call the remove function yet ;) but I think I'll be able to modify the code if necessary). I think that's all that's needed to solve this. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

南风起 2024-10-26 15:05:49

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

  1. 将所有指向目标项目的指针更改为指向目标项目的 next 成员。这将是前一项的 next 指针,或列表 bucket.nodes 的头部。
  2. 释放您刚刚设置为不可访问的节点。

一旦您了解了自己在做什么,操作链表的代码实际上并不那么棘手。

If you know the item you want to remove, you must do two things:

  1. Change all pointers that point to the target item to point to the target item's next member. This will be the preceding item's next pointer, or the head of the list bucket.nodes.
  2. Free the node you just made unreachable.

The code for manipulating a linked list is really not that tricky, once you understand what you are doing.

终弃我 2024-10-26 15:05:49

您的节点除了 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;
 }

Your nodes don't have any payload other than an id, so, depending on the data payload of a node, you might not actually need to iterate the list in the standard way. This is useful if deleters are going to know the address of only the node they want to delete.

If your payload is a pointer to other data:

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

Then you could "delete" a node by stealing the payload of the next node, and then delinking the next node:

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;
 }
素染倾城色 2024-10-26 15:05:49
/* 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);
}
/* 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);
}
彼岸花ソ最美的依靠 2024-10-26 15:05:49
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;
            }
        }
    }
}
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;
            }
        }
    }
}
小嗲 2024-10-26 15:05:49

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

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

该函数删除所有具有 id 的节点(查找)。如果只想删除第一个匹配项,请在 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;
    }
  }
}

Its been a long time ago since I worked with C, but this should be compile clean.

Basically, you need to keep track of the previous pointer while you iterate through the linked list. When you find the node to delete, just change the previous pointer to skip the delete node.

This function deletes all nodes with id (find). If you want to delete only the first occurrence, then put a return after the free statement.

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;
    }
  }
}
南烟 2024-10-26 15:05:49

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

pPrev->next = pCurrent->next;

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

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

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

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

The following does not contain any error checking and only removes the current node from the list ...

pPrev->next = pCurrent->next;

Your preferences may vary, but I tend to put my linked list node at the start of the structure (whenever practical).

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

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

I find this generally helps to simplify pointer arithmetic and allows simple typecasting when needed.

南街女流氓 2024-10-26 15:05:49

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

This removes a node given its address; you can modify it to remove a node given its id, but you haven't specified the form of an id -- is it a NUL-terminated string, or is it 20 bytes?

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

Or, more compactly,

// 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;
}
简单爱 2024-10-26 15:05:49
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");
}
}
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");
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文