Не могли бы вы, пожалуйста, помочь мне решить эту функцию обратного изменения?

#c #linked-list

Вопрос:

Я пытался написать функцию ReverseRange(struct Node **head, int x, int y) , которая перевернет связанный список в заданном диапазоне индексов int x и int y . Я использовал ранее определенную функцию Reverse() в одном из условий, ReverseRange() но она не изменяет данный список, а печатает только один узел с данными 'Q' . Я не знаю, есть ли ошибка в Print() или Reverse() или ReverseRange() или где-то еще. Пожалуйста, помогите, спасибо.

 #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 amp;amp; y == LengthRec(Head)) {
            Reverse(amp;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(amp;Head, 'Q');
    Insert(amp;Head, 'W');
    Insert(amp;Head, 'E');
    Insert(amp;Head, 'R');
    Insert(amp;Head, 'T');
    Print(amp;Head);
    Reverse(amp;Head);
    Print(amp;Head);
    ReverseRange(amp;Head, 1, 5);
    Print(amp;Head);
}
 

Выход:

  T      R       E       W       Q
 Q      W       E       R       T
 Q
 

Ответ №1:

Reverse Функция кажется хорошей, но ее следует вызывать с H аргументом from ReverseRange() , а не amp;Head с локальной переменной.

Некоторые явные тесты в начале функции соответствуют допустимым аргументам и не должны возвращать значение ошибки.

Обратите также внимание, что вы должны задокументировать точную семантику для x и y : в языке Си не является идиоматичным использовать 1 для обозначения первого элемента коллекции, 0 это распространенное явление. y кажется включенным, что также не является идиоматичным, но согласуется с использованием 1 для первого элемента.

Ваша LengthRec функция очень неэффективна и может привести к переполнению стека для очень длинных списков. Используйте цикл вместо рекурсии, так как эта рекурсия не является хвостовой рекурсией.

Вот измененная версия:

 #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 amp;amp; 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 = amp;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=NULLn");
        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(amp;Head, 'E');
    Insert(amp;Head, 'D');
    Insert(amp;Head, 'C');
    Insert(amp;Head, 'B');
    Insert(amp;Head, 'A');
    Print("           Initial list:t", Head);
    Reverse(amp;Head);
    Print("         Reverse(amp;Head):t", Head);
    ReverseRange(amp;Head, 1, 5);
    Print("ReverseRange(amp;Head,1,5):t", Head);
    ReverseRange(amp;Head, 1, 1);
    Print("ReverseRange(amp;Head,1,1):t", Head);
    ReverseRange(amp;Head, 2, 4);
    Print("ReverseRange(amp;Head,2,4):t", Head);
    return 0;
}
 

Выход:

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