4

我想编写一个函数,它获取一个指向链表头的指针,并每隔一个成员就从链表中删除一次。List 是 element 类型的链接元素

typedef struct element{
    int num;
    struct element* next;
}element;

我对所有这些指针算术都很陌生,所以我不确定我是否正确编写它:

 void deletdscnds(element* head) {
    element* curr;
    head=head->next; //Skipping the dummy head//

    while (head!=NULL) {
        if (head->next==NULL) 
            return;

            else {
                curr=head;
                head=head->next->next; //worst case I'll reach NULL and not a next of a null//
                curr->next=head;
            }
        }
    }

我一直在更改它,因为我一直在发现错误。你能指出任何可能的错误吗?

4

2 回答 2

9

如果您根据节点对来考虑链表,则该算法会简单得多。循环的每次迭代都应处理两个节点 -headhead->next,并在退出时head保持等于head->next->next。同样重要的是不要忘记删除中间节点,如果你要将它从列表中删除,否则你会看到内存泄漏。

while (head && head->next) {
    // Store a pointer to the item we're about to cut out
    element *tmp = head->next;
    // Skip the item we're cutting out
    head->next = head->next->next;
    // Prepare the head for the next iteration
    head = head->next;
    // Free the item that's no longer in the list
    free(tmp);
}
于 2012-07-19T17:33:54.803 回答
1

用递归术语可视化这个问题可能是最直接的,如下所示:

// outside code calls this function; the other functions are considered private
void deletdscnds(element* head) {
  delete_odd(head);
}

// for odd-numbered nodes; this won't delete the current node
void delete_odd(element* node) {
  if (node == NULL)
    return; // stop at the end of the list
  // point this node to the node two after, if such a node exists
  node->next = delete_even(node->next);
}

// for even-numbered nodes; this WILL delete the current node
void delete_even(element* node) {
  if (node == NULL)
    return NULL; // stop at the end of the list
  // get the next node before you free the current one, so you avoid
  // accessing memory that has already been freed
  element* next = node->next;
  // free the current node, that it's not needed anymore
  free(node);
  // repeat the process beginning with the next node
  delete_odd(next);
  // since the current node is now deleted, the previous node needs
  // to know what the next node is so it can link up with it
  return next;
}

至少对我来说,这有助于阐明每一步需要做什么。

我不建议实际使用这种方法,因为在 C 中,递归算法可能会占用大量 RAM,并导致不优化它们的编译器导致堆栈溢出。相反,dasblinkenlight 的答案包含您应该实际使用的代码。

于 2012-07-19T18:03:46.347 回答