检查单链接列表是否为回文列表(C)

检查单链接列表是否为回文列表(C),c,pointers,linked-list,palindrome,singly-linked-list,C,Pointers,Linked List,Palindrome,Singly Linked List,我试图检查单链表是否是回文。约束条件是-算法必须在线性时间和恒定空间中 我使用的基本算法如下- 使用快速和慢速指针将列表分成两半 将后半部分反转到位 比较上半场和下半场 重新构造原始列表 返回结果 我的实现适用于元素数为偶数的列表,但如果元素数为奇数,则会失败 /* * @brief Checks if a list is a palindrome or not */ bool is_palindrome(node *head) { node *first;

我试图检查单链表是否是回文。约束条件是-算法必须在线性时间和恒定空间中

我使用的基本算法如下-

  • 使用快速和慢速指针将列表分成两半
  • 将后半部分反转到位
  • 比较上半场和下半场
  • 重新构造原始列表
  • 返回结果
  • 我的实现适用于元素数为偶数的列表,但如果元素数为奇数,则会失败

    /*
     * @brief   Checks if a list is a palindrome or not
     */
    bool is_palindrome(node *head)
    {
        node *first;                /* Points to head node of 1st half */
        node *second;               /* Points to head node of 2nd half */
        node *f_ptr = head;         /* Fast pointer */
        node *s_ptr = head;         /* Slow pointer */
        node *prev = NULL;          /* Previous to slow pointer */
        bool ret = false;           /* Return value */
    
        while (f_ptr && f_ptr->next && f_ptr->next->next)
        {
            prev = s_ptr;
            s_ptr = s_ptr->next;
            f_ptr = f_ptr->next->next;
        }
    
        /* List with even number of elements */
        if (!(f_ptr->next->next))
        {
            first = head;
            second = s_ptr->next;
            s_ptr->next = NULL;
            /* Reverse the second half */
            second = reverse_list(&second);
            /* Compare the first & second half */
            ret = are_identical(first, second);
            /* Finally, construct the original list back */
            second = reverse_list(&second);
            s_ptr->next = second;
            print_list(head);
        }
        /* List with odd number of elements */
        if (!(f_ptr->next))
        {
            first = head;
            second = s_ptr->next;
            prev->next = NULL;
            s_ptr->next = NULL;
            /* Reverse the second half */
            second = reverse_list(&second);
            /* Compare the first & second half */
            ret = are_identical(first, second);
            /* Finally, construct the original list back */
            second = reverse_list(&second);
            prev->next = s_ptr; s_ptr->next = second;
            print_list(head);
        }
        return ret;
    }
    
    有人能帮我弄清楚在处理奇数案时我做错了什么吗?可以找到此程序的完整实现。

    感谢您指出错误。下面是适用于偶数和奇数情况的实现

    /*
     * @brief   Checks if a list is a palindrome or not
     */
    bool is_palindrome(node *head)
    {
        node *first;                /* Points to head node of 1st half */
        node *second;               /* Points to head node of 2nd half */
        node *f_ptr = head;         /* Fast pointer */
        node *s_ptr = head;         /* Slow pointer */
        node *prev = NULL;          /* Previous to slow pointer */
        bool ret = false;           /* Return value */
    
        while (f_ptr && f_ptr->next && f_ptr->next->next)
        {
            prev = s_ptr;
            s_ptr = s_ptr->next;
            f_ptr = f_ptr->next->next;
        }
    
        /* List with odd number of elements */
        if (!(f_ptr->next))
        {
            first = head;
            second = s_ptr->next;
            prev->next = NULL;
            s_ptr->next = NULL;
            /* Reverse the second half */
            second = reverse_list(&second);
            /* Compare the first & second half */
            ret = are_identical(first, second);
            /* Finally, construct the original list back */
            second = reverse_list(&second);
            prev->next = s_ptr; s_ptr->next = second;
            print_list(head);
        }
        /* List with even number of elements */
        else if (!(f_ptr->next->next))
        {
            first = head;
            second = s_ptr->next;
            s_ptr->next = NULL;
            /* Reverse the second half */
            second = reverse_list(&second);
            /* Compare the first & second half */
            ret = are_identical(first, second);
            /* Finally, construct the original list back */
            second = reverse_list(&second);
            s_ptr->next = second;
            print_list(head);
        }
        return ret;
    }
    

    我认为您需要重新搜索下半部分的第一个节点。它需要指向中间节点(偶数情况)或“N div 2+1”节点(奇数情况)。然后你只需旋转一半并穿过它。IMHO您不需要对奇数情况进行任何特殊处理,因为没有为此特定节点设置任何规则。您可以使用此解决方案:当您说您的实现“如果元素数为奇数则失败”时,这意味着什么?发生了什么事?程序崩溃?结果不正确?将列表的前半部分反转(您可以将列表拆分为两半)而不是反转第二部分可能会更容易一些。无论哪种方式,当列表中有奇数个元素时,正如Paul所说,中间的元素对结果都没有影响。这似乎就是你出错的地方。我假设它是错误的,但应该是因为这个
    if!(f_ptr->next->next)
    。如果列表中有奇数个元素,则
    f_ptr
    将指向第一个循环完成后的最后一个元素。因此,
    f_ptr->next
    NULL
    因此
    f_ptr->next->next
    将发生故障。首先尝试检查
    !(f_ptr->next)
    且仅在
    之后!(f_ptr->next->next)