1

这是我之前提出的问题的后续。我仍在学习指针的方法,并且发现在迭代数据结构时很难维护对结构的物理地址的引用。例如,我有一个简单的准系统链表,我想通过搜索指针从中删除:

struct Node{
    int value;
    struct Node* next;
};

struct Node* createNode(int value){
    struct Node* newNode = malloc(sizeof *newNode);
    newNode->value = value;
    newNode->next = NULL;
    return newNode;
}

void nodeDelete(Node **killptr){
    free(*killptr);
    *killptr = NULL;
}

int main(){
    struct Node* head = createNode(16);
    head->next = createNode(25);
    head->next->next = createNode(51);
    head->next->next->next = createNode(5);

    // Working code to delete a specific node with direct reference address
    struct Node** killptr = &head->next;
    nodeDelete(killptr);

    return 0;
}

nodeDelete上面显示了通过将指针传递给头指针的地址来进行删除。我想要做的是能够移动我的指针->next,直到它找到满足删除条件的东西,然后调用nodeDelete它。我尝试了以下方法:

struct Node* searchAndDestroy = head;
while(searchAndDestroy->value != NULL){  // Search until the end of the structure
    if (searchAndDestroy->value == 25){  // If the value == 25
        nodeDelete(&searchAndDestroy);   // Delete the node (FAILS: Nullifies the 
                                         //   address of search variable, not the 
        break;                           //   original node)
    }else{
        searchAndDestroy = searchAndDestroy->next;
    }
}

我也尝试过类似的东西:

if (searchAndDestroy->value == 25){
    struct Node** killptr = (Node**)searchAndDestroy);
    nodeDelete(killptr);                                // Still fails
}

我需要能够将我的指针移动到 ->next 点,但还要保持对我要删除的节点地址的引用(而不是对搜索节点本身地址的引用)。

编辑:一些澄清:我意识到以这种方式从链表中删除是幼稚的,泄漏内存,并且不正确地删除了一半的列表。关键不是要从链表中实际删除。最终的想法是使用它递归地删除二叉搜索树的叶子。我只是认为在问题中描述一个链接列表会更短作为一个例子。

4

3 回答 3

2
struct Node **searchAndDestroy;

for (searchAndDestroy = &head;*searchAndDestroy; searchAndDestroy = &(*searchAndDestroy)->next ){  
    if ((*searchAndDestroy)->value == 25){ 
        nodeDelete(searchAndDestroy); // Function should be changed to assign the ->next pointer to the **pointer  

        break;                           

    }
}

并像这样更改 nodeDelete:

void nodeDelete(Node **killptr){
    Node *sav;
    if (!*killptr) return;
    sav = (*killptr)->next;
    free(*killptr);
    *killptr = sav;
}
于 2012-07-26T20:16:50.650 回答
1

除非我遗漏了什么,否则您的nodeDelete功能按设计工作,但您希望保持访问链中下一个节点的方式。最简单的方法就是添加一个临时变量:

struct Node *searchAndDestroy = head, *temp = NULL;
while(searchAndDestroy != NULL){ // Need to check if the node itself is null before
                                 // dereferencing it to find 'value'
    temp = searchAndDestroy->next;
    if (searchAndDestroy->value == 25){
        nodeDelete(&searchAndDestroy);
        break;
    }else{
        searchAndDestroy = temp;
    }
}
于 2012-07-26T20:07:25.840 回答
0

如果您提供前一个节点的地址,即删除节点的链接所在的位置,那么这是非常简单的代码片段:-

void delete_direct (struct Node *prevNode)
 {/*delete node but restrict this function to modify head .So except first node use this function*/
      struct Node *temp;/*used for free the deleted memory*/
      temp=prevNode->link;
      prevNode->link=temp->link;
      free(temp);
 }

struct Node * find_prev(struct Node *trv_ptr,int ele)
 {
    /*if deleting element found at first node spl operation must be done*/ 
    if(trv_ptr->data==ele)
      return trv_ptr;
    while((trv_ptr->link)&&(trv_ptr->link->data!=ele))
      {
        trv_ptr=trv_ptr->link;
      }
   if(trv_ptr->link==NULL)
     {
         return NULL;
    }
   else
        return trv_ptr;
 }

 main()
  {
    /*finding Node by providing data*/
    struct Node *d_link;
    struct Node *temp;
    d_link=find_prev(head,51);
    if(d_link==NULL)
       {//data ele not present in your list
          printf("\nNOT FOUND\n");
       }
    else if(d_link==head)
      {//found at first node so head is going to change
        temp=head;
        head=head->link;
        free(temp)
      }
    else
     {//other wise found in some where else so pass to function
        delete_direct (d_link);
     }

  }
于 2012-07-27T06:16:58.697 回答