मैं इस फ़ंक्शन का उपयोग एक नए नोड को सामने की ओर धकेल कर एक सूची बनाने के लिए कर रहा हूँ।

void push(struct Node **head, int newValue)
{    
    if (*head == NULL)
    {
        puts("List is empty. The first node will be created now... ");
    }
    struct Node *new_node = malloc(sizeof(struct Node));
    new_node->data = newValue;
    new_node->next = (*head);
    (*head) = new_node;
}

मैं ऐसा करके सूची को पॉप्युलेट कर रहा हूं:

  push(&head, 10);
  push(&head, 20);
  push(&head, 30);
  push(&head, 40);

यह मुझे निम्नलिखित सूची देता है: 40->30->20->10

अब, मैं सूची के शीर्ष पर तत्व को हटाना चाहता हूं। यहां मेरा डिलीट फंक्शन है:

void delete (struct Node **head, int key)
{
    // struct Node *currentNode = (*head);
    
    if ((*head)->data == key)
    {
        struct Node *tmp = (*head);
        (*head) = (*head)->next;
        free(tmp);
    }
}

फिर:

delete(&head, 40);
printList(head);

और मुझे अपेक्षित आउटपुट मिलता है (यानी 30->20->10)।

हालांकि, अगर मैं struct Node *currentNode = (*head); लाइन को अन-टिप्पणी करता हूं और (*head) के बजाय currentNode पॉइंटर का उपयोग करता हूं:

void delete (struct Node **head, int key)
{
    struct Node *currentNode = (*head);

    //if the key is at HEAD (the first node)
    if (currentNode->data == key)
    {
        struct Node *tmp = currentNode;
        currentNode = currentNode->next;
        free(tmp);
    }
}

, और मैं delete(&head, 40) और printList(&head) को फिर से कॉल करता हूं, मुझे लगता है कि कुछ मान कचरा हैं (यानी 0->1)।

मेरा printList यह है:

void printList(struct Node *list)
{
    int index = 0;
    
    while (list != NULL)
    {
        index++;
        list = list->next;
    }
}

और नोड यह है:

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

क्या चल रहा है?

-1
kingJulian 26 जिंदा 2022, 20:52

2 जवाब

सबसे बढ़िया उत्तर

उस मामले में जहां आप currentNode का उपयोग कर रहे हैं, इसमें *head की एक प्रति है। हालांकि, आप केवल कॉपी को संशोधित करते हैं, न कि *head, इसलिए सूची का शीर्ष वास्तव में नहीं बदलता है। इसलिए फ़ंक्शन के वापस आने के बाद, head अब उस मेमोरी की ओर इशारा करता है जिसे मुक्त कर दिया गया है, इसलिए उस पॉइंटर को पढ़ना अपरिभाषित व्यवहार

पॉइंटर-टू-पॉइंटर पास करने का कारण कॉलिंग फ़ंक्शन में पॉइंटर को कॉल किए गए फ़ंक्शन द्वारा संशोधित करने की अनुमति देना है।

3
dbush 26 जिंदा 2022, 20:58
तो, currentNode को पॉइंटर-टू-पॉइंटर वैरिएबल होना चाहिए था?
 – 
kingJulian
26 जिंदा 2022, 21:04
1
हां, अगर आपके पास इसके बजाय struct Node **currentNode = head; था, तो आप इसे उसी तरह इस्तेमाल कर सकते हैं जैसे आपने पहले उदाहरण में head का इस्तेमाल किया था।
 – 
dbush
26 जिंदा 2022, 21:05

वास्तव में आपके पास संशोधित फ़ंक्शन में निम्न जैसा है

int x = 10;
int y = x;
y = 0;

इस कोड स्निपेट के बाद वेरिएबल x अपरिवर्तित रहता है क्योंकि यह वेरिएबल y है जिसे प्रारंभ में वेरिएबल x के मान से प्रारंभ किया गया था जिसे बदल दिया गया था।

फ़ंक्शन के भीतर स्थानीय चर currentNode को पेश करने की कोई आवश्यकता नहीं है।

मुझे संदेह है कि आप फ़ंक्शन को इस तरह बदलना चाहते हैं कि यह किसी भी नोड को हटा देगा (न केवल पहले वाला) जिसका मान पैरामीटर कुंजी के मान के बराबर है।

इस मामले में फ़ंक्शन निम्न तरीके से दिख सकता है:

int delete (struct Node **head, int key)
{
    while ( *head != NULL && ( *head )->data != key )
    {
        head = &( *head )->next;
    } 

    int success = *head != NULL;

    if ( success )
    {
        struct Node *tmp = *head;
        *head = ( *head )->next;
        free( tmp );
    }

    return success;
}
1
Vlad from Moscow 26 जिंदा 2022, 21:13
धन्यवाद! आपने वहां लिखा कोड का यह एक बहुत अच्छा टुकड़ा है।
 – 
kingJulian
26 जिंदा 2022, 21:27
बिलकुल नहीं। आपका स्वागत है।:)
 – 
Vlad from Moscow
26 जिंदा 2022, 21:27