简体   繁体   中英

Reversing a List leads to Seg fault

I'm trying to reverse a Linked list recursively. I have these structs:

typedef Test test;

typedef struct Node {
    test t;
    struct Node *nxt;
} LNode;

typedef struct {
    int size;
    LNode *first;
} L;

Where Test is a struct containing a student name and grade (Grade on a Test).

void recursiveReverse(L * r) {
       LNode * first;
       first = r->first; //first node in list

       reverseList(first);
}

void reverseList(LNode * first) {
    LNode * rest;
    rest = first->nxt;

    reverseList(r,rest);

    first->nxt->nxt = first;
    first->nxt = NULL;

    first = rest;
}

However, I seem to be getting a segfault when attempting this. I'm not allowed to change the parameters arguments for the function recursiveReverse , I'm told that I have to call another function, and use that one as the recursive calling function (Which I have). Any help would be much appreciated.

The most important rule of writing recursive functions is that they must terminate. In simple terms, there must be a condition under which the recursive function does not call itself. This is so-called "base case".

For your list reversal function the base case is when the portion of the list that you must reverse contains exactly one node, because a single-node list is a trivial reverse of itself. Therefore, there needs to be a case inside reverseList where you say something like this:

if (first->nxt == NULL) {
    // Do not go into recursive invocation
    return; // This is not complete yet
}

Another thing that is missing from your code is that the reversed list will have a new head, which is the node that used to be the tail. Your reverseList should return it.

A useful trick to writing the rest of the recursive function is to imagine that the function is already written for you, and call it with the knowledge of what it does, forgetting for a moment of how it does it. In case of list reversal the recursive step is relatively easy: you obtain the head of the reversed list, and then change the next of the current node to point back to the current node.

LNode* reverseList(LNode* list) {
    if (list->nxt == null) {
        return list;
    }
    // Reverse the tail
    LNode *head = reverseList(list->nxt);
    // Invert this node
    list->nxt->nxt = list;
    // Return the result of tail reversal
    return head;
}

The only thing missing at this point is setting the new tail's nxt to NULL . You should do it inside your recursiveReverse function:

void recursiveReverse(L * r) {
    LNode *first = r->first;
    LNode *newHead = reverseList(first);
    first->nxt = NULL;
    r->first = newHead;
}

Demo.

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