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 ポイントに移動できるようにする必要がありますが、(検索ノード自体のアドレスへの参照ではなく) 削除するノードのアドレスへの参照も維持する必要があります。

EDIT:いくつかの明確化:この方法でリンクされたリストから削除することは単純であり、メモリをリークし、リストの半分を不適切に削除することに気付きました。ポイントは、リンクされたリストから実際に削除することではありません。最終的には、これを使用して二分探索木の葉を再帰的に削除するという考えです。リンクされたリストは、例として質問に記載する方が短いと思いました。

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 に答える