c++sortingrecursionlinked-listmergesort

Infinite Recursion error while mergesorting linked list


I am applying mergesort on a linked list. Here's the problem : https://leetcode.com/problems/sort-list/

 void mergesort(ListNode* head,ListNode* low, ListNode* high){
    ListNode* slow = low;
    ListNode* fast = low;
    if (low==high) return;
    while (fast->next && fast->next->next){
        fast = fast->next->next;
        slow = slow->next;
    }
    ListNode* mid = slow;
    ListNode* mid1 = mid->next;
    mid->next == NULL;
    mergesort(head,low,mid);
    mergesort(head,mid1,high);
    merge(head,low,mid,high);
}
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        ListNode* traverse = head;
        while(traverse->next){
            traverse = traverse->next;
        }
        ListNode* high = traverse;
        cout<<high->val;
        ListNode* low = head;
        mergesort(head,low,high);
        return head;
    }
};

I commented out the merge function and the problem still persists but here's the merge code anyway:

void merge(ListNode* head, ListNode* low, ListNode* mid, ListNode* high){
    ListNode* left = low;
    ListNode* right = mid->next;
    ListNode* dummy = new ListNode(-1);
    ListNode* tp = dummy;
    while(right && left!=mid->next){
        if (left->val<right->val){
            dummy->next = left;
            dummy = left;
            left = left->next;
        }
        if (left->val>right->val){
            dummy->next = right;
            dummy = right;
            right = right->next;
        }
    }
    if (right == NULL){
        while (left!=mid->next){
            dummy->next = left;
            left = left->next;
        }
    }
    if (left == mid->next){
        while(right){
            dummy->next = right;
            right = right->next;
        }
    }
    ListNode* start1= tp->next;
    head = start1;
}

I tried to apply merge sort here the same way you would on a linear array. My dry runs say that the base case (low==high) is, infact, being reached . In the editor however, it is not reaching the base case. Its throwing some 'Deadly Signal error':

AddressSanitizer:DEADLYSIGNAL

==22==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc9d343ff8 (pc 0x562648afe76b bp 0x7ffc9d344020 sp 0x7ffc9d344000 T0) ==22==ABORTING


Solution

  • The direct cause of the infinite loop is that you don't break the link between the left and right partition. You have mid->next == NULL;, but that accomplishes nothing. It should be an assignment: mid->next = NULL;

    But besides that issue, there are several other problems:

    Not a problem, but:

    Here is your code with all of the above taken into account and corrected:

    // No need for unused head and high parameters; but return the node that becomes head
    ListNode* merge(ListNode* left, ListNode* right) {
        // Note that the two given lists are disjoint: mid1->next is nullptr.
        ListNode* dummy = new ListNode(-1);
        ListNode* tp = dummy;
        while (right && left) {
            if (left->val < right->val){
                tp->next = left;
                tp = left; // tp is the tail of the sorted part
                left = left->next;
            } else { // Must be an ELSE block (mutually exclusive) 
                tp->next = right;
                tp = right;
                right = right->next;
            }
        }
        if (right == NULL) {
            // No need for a loop here: just attach the remainder:
            tp->next = left;
        } else { // Can be an ELSE block
            tp->next = right;
        }
        // Assigning to `head` serves no purpose (`head` was a call-by-value parameter)
        return dummy->next; // Instead: return the head of the sorted list
    }
    
    // No need for three parameters; but return the new head
    ListNode* mergesort(ListNode* head){
        if (!head->next) return head; // Adapated condition (no need for high)
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast->next && fast->next->next){
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode* high = fast->next ? fast->next : fast; // Define high
        ListNode* mid = slow;
        ListNode* mid1 = mid->next;
        mid->next = nullptr; // Assign! And don't use NULL in C++
        head = mergesort(head); // Get the first node back
        mid1 = mergesort(mid1); // (idem)
        return merge(head, mid1); // Return the first node of the result
    }
    
    
    class Solution {
    public:
        ListNode* sortList(ListNode* head) {
            if (!head) return head;
            // No need to get the tail node here
            return mergesort(head); // Return the new head
        }
    };