簡體   English   中英

反向鏈接列表而不修改頭部指針

[英]Reversing a linked list without modifying the head pointer

我正在編寫一個程序來檢查單鏈列表是否是回文。 我的方法如下:

  1. 創建一個單鏈列表
  2. 反轉列表並將其存儲在另一個變量中
  3. 比較兩者。

反向操作會修改頭指針。 為了不修改head指針,我創建了一個temp變量來指向head並使用相同的反向列表並返回temp指針。 操作如下:

struct node* reverse()
{
    struct node *temp=head;
    struct node *curr=temp, *prev=NULL, *next=NULL;
    while(curr!=NULL)
    {
          next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    temp = prev;
    return temp;
}

現在,我的回文功能實現如下:

int isPalindrome()
{
    struct node *temp=head, *rev=head;
    rev = reverse();
    while(temp!=NULL)
    {
        if(temp->data != rev->data)
            return 0;
        temp = temp->next;
        rev = rev->next;
    }
    return 1;
}

如果反向列表和原始列表節點不匹配,則返回0。否則返回1。

它適用於一些測試案例。 但是當列表是1-> 4-> 3-> 2-> 1時。 它返回1,但應該返回0。

在鍛煉時,我發現, rev函數修改了頭指針。 現在,我的列表只有一個節點。

輸出如下所示:
在此處輸入圖片說明

  1. 第一個列表在打印時未修改頭指針
  2. 第二個列表是反向列表
  3. 調用reverse函數后,第三個列表將打印原始列表

反轉原始頭后,指向反轉列表中的最后一個元素,這就是為什么您在第三個輸出中僅看到一個元素的原因。 有幾個選項供您選擇:

  1. 使用雙鏈表。 從頭和尾同時以相反的方向移動。

  2. 反轉之前,請復制原始列表並比較兩個列表。

  3. 使用堆棧或其他數據結構來提供幫助(類似於上面的選項2)。

  4. 修改算法以僅使用原始列表。

顯然,功能reverse是錯誤的,因為它將建立一個新列表。 這意味着它必須基於原始列表的節點為反向列表創建新的節點。 也就是說,它必須使用標准函數malloc在內存中分配其節點。

另外,定義一個將比較兩個列表的函數在邏輯上更加一致。 使用此功能,您可以說列表是否為回文。

這是一個演示程序,您可以將其用作自己程序的示例。

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

struct node
{
    int data;
    struct node *next;
};

void push_front( struct node **head, int data )
{
    struct node *n = malloc( sizeof( struct node ) );

    n->data = data;
    n->next = *head;

    *head = n;
}

void display( struct node *head )
{
    for ( ; head != NULL; head = head->next )
    {
        printf( "%d ", head->data );
    }
    printf( "\n" );
}

struct node * reverse_copy( struct node *head )
{
    struct node *rev_head = NULL;

    for ( ; head != NULL; head = head->next )
    {
        push_front( &rev_head, head->data ); 
    }

    return rev_head;
}

int equal( struct node *head1, struct node *head2 )
{
    while ( head1 != NULL && head2 != NULL && head1->data == head2->data )
    {
        head1 = head1->next;
        head2 = head2->next;
    }

    return head1 == NULL && head2 == NULL;
}

void free_list( struct node **head )
{
    struct node *n = *head;

    while ( n != NULL )
    {
        struct node *tmp = n;
        n = n->next;
        free( tmp );
    }

    *head = NULL;
}

struct node *head;

int main(void) 
{
    push_front( &head, 1 );
    push_front( &head, 2 );
    push_front( &head, 3 );
    push_front( &head, 4 );
    push_front( &head, 1 );

    display( head );

    struct node *rev_head = reverse_copy( head );

    if ( equal( head, rev_head ) )
    {
        printf( "The list is a palindrome\n" );
    }
    else
    {
        printf( "The list is not a palindrome\n" );
    }

    free_list( &head );
    free_list( &rev_head );

    push_front( &head, 1 );
    push_front( &head, 2 );
    push_front( &head, 3 );
    push_front( &head, 2 );
    push_front( &head, 1 );

    display( head );

    rev_head = reverse_copy( head );

    if ( equal( head, rev_head ) )
    {
        printf( "The list is a palindrome\n" );
    }
    else
    {
        printf( "The list is not a palindrome\n" );
    }

    free_list( &head );
    free_list( &rev_head );

    return 0;
}

程序輸出為

1 4 3 2 1 
The list is not a palindrome
1 2 3 2 1 
The list is a palindrome

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM