简体   繁体   中英

Merge Sort Singly Linked List in C++ failing for large input

Update. its working for 65,519 in the FOR LOOP. If i increase it to 65,520, it fails. Completely strange.

This program is not working for large inputs. It is perfect for small inputs. I am getting an exception on Xcode.

Thread 1 : EXC_BAD_ACCESS (code=2, address = 0x7fff5f3fffb8).

Kindly let me know how I can bypass this strange error.

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
typedef struct Node * nodePtr;

struct Node{

    int data;
    nodePtr next;

};

nodePtr globalHead;

void partition(nodePtr head, nodePtr *front, nodePtr *back){

    nodePtr fast;
    nodePtr slow;

    if (head == NULL || head->next == NULL){

        *front = head; // &a
        *back = NULL; // &b

    }else{

        slow = head;
        fast = head->next;

        while(fast != NULL){

            fast = fast->next;

            if(fast != NULL){

                slow = slow->next;
                fast = fast->next;

            }

        }

        *front = head; // a
        *back = slow->next; // b
        slow->next = NULL;
        //printList(*front);
        //printList(*back);

    }

}

nodePtr mergeLists(nodePtr a, nodePtr b){

    nodePtr mergedList = NULL;

    if (a == NULL){
        return b;
    }else if (b == NULL){
        return a;
    }

        try {



    if (a->data <= b->data){
        mergedList = a;
        mergedList->next = mergeLists(a->next, b);
    }else{
        mergedList = b;
        mergedList->next = mergeLists(a, b->next);
    }
    }
    catch (int e) {
        cout << "Error is . . " << e << endl;
    }

    return mergedList;

}

void mergeSort(nodePtr *source){

    nodePtr head = *source;
    nodePtr a = NULL;
    nodePtr b = NULL;

    if(head == NULL || head->next == NULL){

        return;

    }

    partition(head, &a, &b);

    mergeSort(&a);
    mergeSort(&b);

    *source = mergeLists(a, b);

}

void push(nodePtr *head, int data){

    nodePtr newNode = (nodePtr) malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;

    if ((*head) == NULL){
        *head = newNode;
        globalHead = *head;
    }else{
        (*head)->next = newNode;
        *head = newNode;
    }

}

void printList(nodePtr head){

    nodePtr current = head;
    while(current != NULL){
        printf("%d ",current->data);
        current = current->next;
    }
    printf("\n");

}

// *head = head in the main function,
// it is only there to connect the two and
// not let make the function return anything
// passed by reference
// globalHead points to the start of the linked list
// if you are passing the address over here you have to
// make a double pointer over there in the function

int main(void)
{
    nodePtr head = NULL;

    // linked list is formed from top to bottom fashion
    // push is done in constant time O(1)

    long long int i;


    //Pushing 200,000 Elements to the Linked List.
    for(i=1 ; i<=200000 ; i++) {
        push(&head, rand()%200000);
    }



    printList(globalHead);

    mergeSort(&globalHead);

    cout << "After Sorting . . \n";

    printList(globalHead);

    return 0;
}

Using recursion mergeLists() is the issue, it will call itself for every node on the list. Try changing the code so that the code loops and appends nodes to the initially empty mergeList, using a second pointer to node, or optionally a pointer to pointer to node which is initially set to &mergeList. For example, using the name pMerge instead of mergeList:

Node * mergeLists(Node *a, Node *b)
{
Node *pMerge = NULL;                    // ptr to merged list
Node **ppMerge = &pMerge;               // ptr to pMerge or prev->next
    if(a == NULL)
        return b;
    if(b == NULL)
        return a;
    while(1){
        if(a->data <= b->data){         // if a <= b
            *ppMerge = a;
            a = *(ppMerge = &(a->next));
            if(a == NULL){
                *ppMerge = b;
                break;
            }
        } else {                        // b <= a
            *ppMerge = b;
            b = *(ppMerge = &(b->next));
            if(b == NULL){
                *ppMerge = a;
                break;
            }
        }
    }
    return pMerge;
}

Here is example code of a fast method to sort a linked list using an array of pointers to lists aList[], where aList[i] points to a list of size 2 to the power i, that makes use of mergeLists().

#define NUMLISTS 32                     // size of aList
Node * mergeSort(NODE *pList)
{
Node * aList[NUMLISTS];                 // array of pointers to lists
Node * pNode;
Node * pNext;
int i;
    if(pList == NULL)                   // check for empty list
        return NULL;
    for(i = 0; i < NUMLISTS; i++)       // zero array
        aList[i] = NULL;
    pNode = pList;                      // merge nodes into array
    while(pNode != NULL){
        pNext = pNode->next;
        pNode->next = NULL;
        for(i = 0; (i < NUMLISTS) && (aList[i] != NULL); i++){
            pNode = mergeLists(aList[i], pNode);
            aList[i] = NULL;
        }
        if(i == NUMLISTS)
            i--;
        aList[i] = pNode;
        pNode = pNext;
    }
    pNode = NULL;                       // merge array into one list
    for(i = 0; i < NUMLISTS; i++)
        pNode = mergeLists(aList[i], pNode);
    return pNode;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM