एक लिंक किए गए सूची तत्व को हटाने से अनंत लूप - सी, लूप, लिंक-सूची, अनंत का कारण बनता है

मैं एक प्रोग्राम लिख रहा हूं जो इनपुट में पूर्णांक की एक सूची लेता है, और पूर्णांक के आधार पर यह निम्न परिचालन करता है:

  1. इनपुट में मान नकारात्मक है तो पूर्ण मूल्य को हटा दें

  2. यदि संख्या सकारात्मक है और फिर भी, सूची के शीर्ष पर जोड़ें

  3. यदि संख्या सकारात्मक और विषम है, तो इसे सूची की पूंछ पर जोड़ें

  4. यदि संख्या शून्य के बराबर है, तो प्रोग्राम समाप्त करें और सूची मुद्रित करें।

मेरी समस्या pop_el फ़ंक्शन के साथ है, जो सूची पर एक अनंत लूप का कारण बनती है, इसलिए जब मैं सूची मुद्रित करता हूं तो प्रोग्राम एक अनंत लूप में जाता है। यह मेरा कोड है:

#include <stdio.h>
#include <stdlib.h>

typedef struct ll_node_S * ll_node_ptr;
struct ll_node_S
{
int v;
ll_node_ptr next;
};
typedef struct ll_node_S ll_node;

ll_node_ptr push_tail(ll_node_ptr head, int v)
{
ll_node_ptr backup = head;
ll_node_ptr current = head;

while(current->next != NULL)
{
current = current->next;
}
current->next = (ll_node_ptr) malloc(sizeof(ll_node));
current->v = v;
return backup;
}

ll_node_ptr push_head(ll_node_ptr head, int v)
{
ll_node_ptr new_head = (ll_node_ptr)malloc(sizeof(ll_node));
new_head->v = v;
new_head->next = head;
return new_head;
}

ll_node_ptr pop_el(ll_node_ptr head, int el)
{
ll_node_ptr backup = head;
ll_node_ptr current = head;
ll_node_ptr previous = NULL;
int found = 0;

while(current != NULL && !found)
{
if(current->v == el)
{
if(previous == NULL)
{
backup = current->next;
free(current);
current = backup;
previous = current;
}
else
{
previous->next = current ->next;
free(current);
current = current->next;
}

found = 1;
}
else
{
previous = current;
current = current->next;
}
}
return backup;
}

void print(ll_node_ptr head)
{
ll_node_ptr current = head;
printf("%dn", head->v);
while(current->next != NULL)
{
current = current->next;
printf("%dn", current->v);
}
}

int isPair(int n)
{
return ((n % 2) == 0);
}

int main(int argc, char** argv)
{
int n = 1;
ll_node_ptr list = NULL;
while(n != 0)
{
scanf("%d", &n);

if(n < 0)
{
list = pop_el(list, -n);
}
else
{
if(isPair(n))
{
list = push_head(list, n);
}
else
{
list = push_tail(list, n);
}

}


}

print(list);
//should free the list
return 0;
}

और यह परीक्षण केस है (इनपुट में पारित) मैं इसके खिलाफ कोड का परीक्षण कर रहा हूं:

4
5
2
-4
-5
-3
9
2
0

जो निम्नलिखित आउटपुट का उत्पादन करना चाहिए:

2
2
9

कोई सुराग?

उत्तर:

उत्तर № 1 के लिए 1

कई चीजे,

में pop_el,

1. यदि previous है NULL तो आपको बस अपना स्थानांतरित करने की जरूरत है head अगले नोड के लिए पीटीआर। ताकि यह नया हो जाएगा head

if(previous == NULL)
{
backup = current->next;
free(current);
//current = backup;   ---> Not needed.
//previous = current; ---> Not needed.
break;  //            ---> No need of setting found flag. You can remove it
}

2. अगर पिछले नहीं है NULL तो आपको बस इंगित करने की आवश्यकता है previous नोड अगले पीआरटी current नोड का अगला नोड।

else
{
previous->next = current ->next;
free(current);
//current = current->next; ---> Not needed.
break;  //            ---> No need of setting found flag. You can remove it
}

3.In push_tail आप के लिए स्मृति आवंटित कर रहे हैं current->next नोड और अगली पंक्ति में आप जोड़ रहे हैं v वर्तमान नोड के लिए v। वह गलत है। निम्नलिखित जांचें,

ll_node_ptr push_tail(ll_node_ptr head, int v)
{
ll_node_ptr backup = head;
ll_node_ptr current = head;
ll_node_ptr new = NULL; // Created new pointer
while(current->next != NULL)
{
current = current->next;
}
//current->next = (ll_node_ptr) malloc(sizeof(ll_node));
new = (ll_node_ptr) malloc(sizeof(ll_node));
//current->v = v;   ----> incorrect. new Value is actually replacing the old value.
new->v = v;       // New value is added in the newly created node.
new->next = NULL;
current->next = new;
return backup;
}

4. आप अपना सुधार कर सकते हैं print तर्क

void print(ll_node_ptr head)
{
ll_node_ptr current = head;
//printf("%dn", head->v);
while(current != NULL)
{
printf("%dn", current->v);
current = current->next;
}
}

जवाब के लिए 0 № 2

आपकी तत्काल समस्या को हल करके हल किया जा सकता है push_tail() समारोह, जैसा कि @Vitek द्वारा इंगित किया गया है। मूल कोड न केवल गलत नोड में मान संग्रहीत करता है, बल्कि यह सेट करने में विफल रहा है next नए आवंटित पूंछ नोड के क्षेत्र में NULL। इस समारोह में एक और समस्या है: दोनों push_head() और यह push_tail() कार्यों को एक नोड पॉइंटर बनाने और वापस करने की आवश्यकता होती है जब एक के साथ बुलाया जाता है NULL head सूचक। असली push_head() समारोह यह करता है, लेकिन push_tail() समारोह नहीं करता है। यदि उपयोगकर्ता द्वारा दर्ज किया गया पहला नंबर अजीब है, तो पहले नोड को सूची में जोड़ा जाता है push_tail() कार्य, अपरिभाषित व्यवहार की ओर अग्रसर होता है (संभवतः एक सेगमेंटेशन गलती)।

सबसे महत्वपूर्ण बात यह है कि आपको अपने कोड को सरल बनाने पर काम करना चाहिए। इससे लिखना आसान हो जाएगा, और डीबग करना आसान हो जाएगा। उदाहरण के लिए, आपका print() समारोह को तीन पंक्तियों में घटाया जा सकता है:

void print(ll_node_ptr current)
{
while(current) {
printf("%dn", current->v);
current = current->next;
}
}

सुधार करने के लिए कई चीजें की जा सकती हैं push_tail() समारोह। यहां एक नया संस्करण है:

ll_node_ptr push_tail(ll_node_ptr head, int v)
{
ll_node_ptr current = head;
ll_node_ptr prev = NULL;
ll_node_ptr tail = malloc(sizeof(ll_node));

if (tail == NULL) {
fprintf(stderr, "Tail node allocation errorn");
exit(EXIT_FAILURE);
}

tail->v = v;
tail->next = NULL;

while (current) {
prev = current;
current = current->next;
}

if (head) {
prev->next = tail;
} else {
head = tail;
}

return head;
}

आपको परिणाम डालने की जरूरत नहीं है malloc()राय इस बात पर भिन्न होती है कि आपको ऐसा करना चाहिए या नहीं, लेकिन कलाकार के बिना लेखन कोड को सरल बनाता है। इसके अलावा, आपको यह सुनिश्चित करने के लिए जांच करनी चाहिए malloc() अनुरोधित स्मृति सफलतापूर्वक आवंटित किया है। यदि आप इसके बजाय उपयोग कर रहे हैं तो यह विशेष रूप से महत्वपूर्ण है realloc(), क्योंकि ऐसा करने में विफल होने से स्मृति रिसाव हो सकता है। नई पूंछ नोड यहां बनाई जाने के बाद, v तथा next खेतों को तुरंत सेट कर रहे हैं।

यह आमतौर पर एक लिंक सूची में फिर से शुरू करने के लिए आसान लगता है current नोड, बजाय देखकर current->next नोड। का प्रयोग prev नोड सूचक यह सुविधा प्रदान करता है। नया फ़ंक्शन तब तक सूची में पुन: सक्रिय होता है current == NULL, किस बिंदु पर prev सूची के अंतिम नोड को इंगित करता है। घटना में है कि head एक के रूप में पारित किया गया था NULL सूचक (यानी, सूची खाली थी, जो तब हो सकती है जब उपयोगकर्ता द्वारा दर्ज किया गया पहला नंबर अजीब है) पुनरावृत्ति पाश छोड़ दिया गया है, क्योंकि current शुरू किया गया है head। लूप के बाद कोड सेट करता है next अंतिम नोड का क्षेत्र नव निर्मित पूंछ नोड को इंगित करने के लिए इंगित करता है यदि फ़ंक्शन को एक गैर-सूची सूची दी गई हो, अन्यथा head नई पूंछ नोड बन जाता है। आखिरकार, head कॉलिंग समारोह में वापस आ गया है।

बहुत सरलता है जिसे लागू किया जा सकता है pop_el() समारोह, और बहुत सारे आवश्यक कोड। यह फ़ंक्शन वास्तव में पूरी तरह से फिर से डिज़ाइन किया जाना चाहिए। आपके पास कहां है:

previous->next = current ->next;
free(current);
current = current->next;

आपके पास freeडी द्वारा संदर्भित स्मृति current, तो आप सूचक को इस स्मृति में dereference करने की कोशिश करें। कॉल करने के बाद free(), अब आप इस स्मृति के मालिक नहीं हैं, और यह है अपरिभाषित व्यवहार। इसके बजाय आप चाहते हैं:

current = previous->next;

लेकिन यह वास्तव में कोई फर्क नहीं पड़ता, क्योंकि found अगला सेट है 1, लूप समाप्त हो जाता है, और समारोह returnरों backup, के साथ और अधिक उपयोग के साथ current। आपको उपरोक्त असाइनमेंट को केवल हटा देना चाहिए current चूंकि इसकी आवश्यकता नहीं है।

आप अपने कार्यक्रम में शेष कोड को बेहतर बनाने के लिए इस जानकारी का उपयोग करने में सक्षम होना चाहिए। ऐसे अन्य मुद्दे हैं जिन्हें आप देखना चाहते हैं। यह आमतौर पर एक बुरा अभ्यास है typedef पॉइंटर्स - यह केवल कोड को खराब करने में काम करता हैऔर प्रोग्रामिंग त्रुटियों की संभावना बढ़ जाती है। आपके द्वारा प्रदान किया गया विनिर्देश यह स्पष्ट नहीं करता है कि क्या होना चाहिए यदि समान मान वाले एकाधिक नोड्स हों, यानी, एक या सभी को हटा दिया जाना चाहिए? और, यदि उपयोगकर्ता द्वारा दर्ज किया गया पहला नंबर है तो क्या होगा 0?


उत्तर № 3 के लिए -1

सबसे पहले मैं सूचियों के साथ काम करते समय रिकर्सिव फ़ंक्शंस का उपयोग करने का सुझाव दूंगा। डीबग और समझने के लिए यह बहुत आसान है।

मुझे लगता है कि मुझे आपके push_tail फ़ंक्शन के साथ कोई समस्या मिली है:

current->next = (ll_node_ptr) malloc(sizeof(ll_node));
current->v = v;

आप वर्तमान के लिए स्मृति आवंटित करते हैं-> अगला लेकिन वर्तमान नोड को मान असाइन करें। यह होना चाहिए

current->next = (ll_node_ptr) malloc(sizeof(ll_node));
current->next->v = v;
current->next->next = NULL;

शायद यह आपकी समस्या से कुछ करने के लिए है।


संबंधित सवाल
सबसे लोकप्रिय