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
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:
In
mergeyou assume thatright = mid->next;will assign the first node of the second list, but that is not true once you have fixed the issue above. You had just cut the two sublists, somid->nextis always going to be null. This also means a condition likeleft!=mid->nextis no different from sayingleft!=nullptr. You should instead pass the head node of the second list as argument tomerge, and let it beright.As
headis a call-by-value parameter, assigning to it does not affect the caller's variable with the same name. So for example, the assignmenthead=start1at the end of your code, is useless. By consequence, the caller will not know what the first node is of the sorted list. You could solve this by using a call-by-reference parameter, or return the head node reference (I will go with that latter option in the below solution).sortListis not designed to deal with an empty list. It should check the case whereheadis null.In
mergethere will be an infinite loop whenleft->val==right->val. In that case the loop body doesn't do anything, and so the loop condition will remain unchanged. Related to this problem is that the secondifcondition could hit a null-pointer (left) when the firstifblock had executed at a momentleftwas the last node of that list. Both issues are solved if you make combine the twoifblocks into anif ... elseconstruct.Not a problem, but:
If
tpis short for tail pointer, then you have inverted the use ofdummyandtp. Your loop advancesdummyto reference the tail of the already sorted part, while you leavetppointing to the dummy node. It would make more sense if you had done the opposite, and leftdummyreferencing the dummy node, andtpthe tail.As you already have a
fastpointer that will reach the end of the list, there is no need to have separate code to find the end of the list (insortList). Instead, just pass one argument tomergeSortand letfasthelp you to identify the tail (what you calledhigh) of your list.In C++ you really should use
nullptrinstead ofNULLAt the end of
merge, after the main loop, you don't need another loop to attach the remaining nodes. It suffices to just link the remainder to the tail of the sorted part. All the next links after that do not have to change.mergedoesn't use thehighparameter, nor does it need it.Here is your code with all of the above taken into account and corrected: