Can you please help me resolve this ReverseRange Function?

Viewed 36

I was trying to write a function ReverseRange(struct Node **head, int x, int y) which will reverse a linked list in given range of indices int x and int y. I used a previously defined function Reverse() in one of condition in ReverseRange() but it is not reversing the given list, only printing only one Node with data 'Q'. I don't know if the error is in Print() or Reverse() or ReverseRange() or elsewhere. Please help, Thank you.

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

struct Node {
    char data;
    struct Node *next;
};

//insert data in the node
void Insert(struct Node **Head, char data) {
    struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
    temp->data = data;
    temp->next = *Head;
    *Head = temp;
}

//find length of linked list 
int LengthRec(struct Node *head) {
    if (head == NULL)
        return 0;
    return 1 + LengthRec(head->next);
}

//Reverse a linked list when head is given;
void Reverse(struct Node **head) {
    struct Node *prev = NULL;
    struct Node *curr = *head;
    struct Node *next = NULL;
    while (curr != NULL) {
        next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    *head = prev;
}

//Reverse list in range x to y;
int ReverseRange(struct Node **H, int x, int y) {
    struct Node *Head = *H;
    if (Head == NULL)
        return -1;
    else if (Head->next == NULL)
        return -1;
    else if (x == y)
        return -1;
    else if (x > y)
        return -1;
    else if (LengthRec(Head) >= y) {
        if (x == 1 && y == LengthRec(Head)) {
            Reverse(&Head);
            return 1;
        }
        /* NOTE:: 
           Code is incomplete, because I found error before
           the entire code is written,
        */
    }
}

void Print(struct Node **H) {
    struct Node *head = *H;
    if (head == NULL) {
        printf("Head=NULL");
        return;
    }
    printf("\n %c", head->data);
    while (head->next != NULL) {
        head = head->next;
        printf("\t%c", head->data);
    }
}

int main() {
    struct Node *Head = NULL;
    Insert(&Head, 'Q');
    Insert(&Head, 'W');
    Insert(&Head, 'E');
    Insert(&Head, 'R');
    Insert(&Head, 'T');
    Print(&Head);
    Reverse(&Head);
    Print(&Head);
    ReverseRange(&Head, 1, 5);
    Print(&Head);
}

Output:

 T      R       E       W       Q
 Q      W       E       R       T
 Q
1 Answers

The Reverse function seems fine, but it should be called with H as an argument from ReverseRange(), not &Head which is a local variable.

Some of the explicit tests at the beginning of the function correspond to legitimate arguments, and should not return an error value.

Note also that you should document the precise semantics for x and y: it is not idiomatic in C to use 1 to designate the first element of a collection, 0 is mote common. y seems included, which is not idiomatic either but consistent with using 1 for the first element.

Your LengthRec function is very inefficient and may cause a stack overflow for very long lists. Use a loop instead of recursing as this recursion is not a tail recursion.

Here is a modified version:

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

struct Node {
    char data;
    struct Node *next;
};

//insert data in the node
void Insert(struct Node **Head, char data) {
    struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
    temp->data = data;
    temp->next = *Head;
    *Head = temp;
}

//find length of linked list
int ListLength(const struct Node *head) {
    int length = 0;
    while (head != NULL) {
        length++;
        head = head->next;
    }
    return length;
}

//Reverse a linked list when head is given;
void Reverse(struct Node **head) {
    struct Node *prev = NULL;
    struct Node *curr = *head;
    while (curr != NULL) {
        struct Node *next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    *head = prev;
}

//Reverse list in range x to y;
int ReverseRange(struct Node **H, int x, int y) {
    int length = ListLength(*H);

    if (x < 1 || x > length || x > y || y > length)
        return -1;
    if (x == y)
        return 1;
    if (x == 1 && y == length) {
        Reverse(H);
        return 1;
    } else {
        struct Node **head = H;
        struct Node *prev = NULL;
        struct Node *curr = *head;
        struct Node *last;

        while (x > 1) {
            head = &curr->next;
            curr = *head;
            x--;
            y--;
        }
        last = curr;
        while (x <= y) {
            struct Node *next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
            x++;
        }
        last->next = curr;
        *head = prev;
        return 1;
    }
}

void Print(const char *msg, const struct Node *head) {
    if (msg) {
        printf("%s", msg);
    }
    if (head == NULL) {
        printf("Head=NULL\n");
        return;
    }
    printf("%c", head->data);
    while (head->next != NULL) {
        head = head->next;
        printf("\t%c", head->data);
    }
    printf("\n");
}

int main() {
    struct Node *Head = NULL;
    Insert(&Head, 'E');
    Insert(&Head, 'D');
    Insert(&Head, 'C');
    Insert(&Head, 'B');
    Insert(&Head, 'A');
    Print("           Initial list:\t", Head);
    Reverse(&Head);
    Print("         Reverse(&Head):\t", Head);
    ReverseRange(&Head, 1, 5);
    Print("ReverseRange(&Head,1,5):\t", Head);
    ReverseRange(&Head, 1, 1);
    Print("ReverseRange(&Head,1,1):\t", Head);
    ReverseRange(&Head, 2, 4);
    Print("ReverseRange(&Head,2,4):\t", Head);
    return 0;
}

Output:

           Initial list:        A       B       C       D       E
         Reverse(&Head):        E       D       C       B       A                                                                           ReverseRange(&Head,1,5):        A       B       C       D       E
ReverseRange(&Head,1,1):        A       B       C       D       E
ReverseRange(&Head,2,4):        A       D       C       B       E
Related