【问题标题】:Reverse a linked list using recursion使用递归反转链表
【发布时间】:2020-07-22 13:03:11
【问题描述】:

void reve(struct Node *head)display(struct Node *head) 方法采用一个参数 - 链表的头部。我想打印整个链表,但我的显示功能只打印4

#include <iostream>

using namespace std;

struct Node {
    int data;
    struct Node *link;
};

void display(struct Node *head) {
    if (head == NULL) {
        return;
    }
    cout << head->data << "\t";
    display(head->link);
    //head = head->link;
}

struct Node *reve(struct Node *head) {
    struct Node *p = head;
    if (p->link == NULL) {
        head = p;
        return head;
    }
    reve(p->link);
    struct Node *temp = p->link;
    temp->link = p;
    p->link = NULL;
}

struct Node *insert(struct Node *head, int new_data) { 
    Node *new_node = new Node(); 
    new_node->data = new_data; 
    new_node->link = head; 
    head = new_node; 
    return head;
}

int main() {
    Node *head = NULL;
    head = insert(head, 1);
    head = insert(head, 2);
    head = insert(head, 3);
    head = insert(head, 4);
    cout << "The linked list is: ";
    //display(head);
    head = reve(head);
    display(head);
    return 0;
}

输出

【问题讨论】:

    标签: c++ linked-list reverse singly-linked-list function-definition


    【解决方案1】:

    如果p-&gt;link 不是NULL,则函数reve 不会返回值。

    由于head 有多个元素,head = reve(head); 具有未定义的行为。

    在一个简单的循环中实现反向链表比使用递归要容易得多:

    struct Node *reve(struct Node *p) {
        if (p != NULL) {
            struct Node *prev = NULL;
            while (p->link) {
                struct Node *next = p->link;
                p->link = prev;
                prev = p;
                p = next;
            }
        }
        return p;
    }
    

    如果您的任务需要递归,您可以提取第一个节点,反转列表的其余部分并附加第一个节点。请注意,这不是尾递归,因此任何足够长的列表都可能导致堆栈溢出

    struct Node *reve(struct Node *head) {
        if (head != NULL && head->link != NULL) {
            struct Node *first = head;
            struct Node *second = head->link;
            head = reve(second);
            first->link = NULL;   // unlink the first node
            second->link = first; // append the first node
        }
        return head;
    }
    

    【讨论】:

    • 我的任务是使用递归反向链接列表。我知道使用循环的方法。
    • @MukulTarania:我添加了一个递归版本。您的方法缺少一些步骤。
    【解决方案2】:

    如果你想要递归方式:

    Node* reverse(Node* head) 
    
    { 
    
        if (head == NULL || head->next == NULL) 
    
            return head; 
    
    
    
        /* reverse the rest list and put  
    
          the first element at the end */
    
        Node* rest = reverse(head->next); 
    
        head->next->next = head;
    
        head->next = NULL; 
    
        /* fix the head pointer */
    
        return rest; 
    
    } 
    
    
    
    /* Function to print linked list */
    
    void print() 
    
    { 
    
        struct Node* temp = head; 
    
        while (temp != NULL) { 
    
            cout << temp->data << " "; 
    
            temp = temp->next; 
    
        } 
    
    } 
    

    【讨论】:

      【解决方案3】:

      在 C++ 中,当已声明的结构或类用作类型说明符时,您无需使用关键字 structclass

      函数reve 具有未定义的行为。

      首先head 可以等于nullptr。在这种情况下这个语句

      if (p->link == NULL) {
      

      调用未定义的行为。

      其次,当p-&gt;link 不等于nullptr 时,该函数不返回任何内容。

          //...
          reve(p->link);
          struct Node *temp = p->link;
          temp->link = p;
          p->link = NULL;
      }
      

      这是一个演示程序,展示了如何实现这些功能。当结构用作类型说明符时,我使用了包含关键字 struct 的 C 方法。

      #include <iostream>
      
      struct Node
      {
          int data;
          struct Node *link;
      };
      
      struct Node * insert( struct Node *head, int data )
      {
          return head = new Node{ data, head };
      }
      
      struct Node * reverse( struct Node *head )
      {
          if ( head && head->link )
          {
              struct Node *tail = head;
      
              head = reverse( head->link );
      
              tail->link->link = tail;
              tail->link = nullptr;
          }
      
          return head;
      }
      
      std::ostream & display( struct Node *head, std::ostream &os = std::cout )
      {
          if ( head )
          {
              os << head->data;
              if ( head->link )
              { 
                  os << '\t';
                  display( head->link, os );
              }
          }
      
          return os;
      }
      
      int main() 
      {
          struct Node *head = nullptr;
      
          const int N = 10;
      
          for ( int i = 0; i < N; i++ )
          {
              head = insert( head, i );
          }   
      
          display( head ) << '\n';
      
          head = reverse( head );
      
          display( head ) << '\n';
      
          return 0;
      }
      

      程序输出是

      9   8   7   6   5   4   3   2   1   0
      0   1   2   3   4   5   6   7   8   9
      

      【讨论】:

        【解决方案4】:

        display 很好。

        我注意到的第一件事是您正在尝试修改复制的值。例如第 16 行。此代码无效。

        请注意,您在插入时有一个错误:您返回 head 而不是 new_node

        对于超过 1 项的列表,您的版本失败。 reve() 应该返回原始列表的最后一个节点,而您没有这样做,因此 lastNode 不会指向反向列表的最后一个节点。所以我的建议是你把它放在一边。

        所以,reve

        struct Node* reve(struct Node* head) {
            if (head->link == NULL) {
                return head;
            }
        
            struct Node* lastNode = reve(head->link);
            lastNode->link = head;
            head->link = NULL;
        
            return head;
        }
        

        main:

        int main() {
            Node* head = NULL;
            Node* last_node = head = insert(head, 1);
            head = insert(head, 2);
            head = insert(head, 3);
            head = insert(head, 4);
            head = reve(head);
            cout << "The linked list is: ";
            // Now, last_node is the new head
            display(last_node);
            return 0;
        }
        

        【讨论】:

        • 您的版本对于超过 1 项的列表失败。 reve() 应该返回原始列表的最后一个节点,而您没有这样做,因此 lastNode 不会指向反向列表的最后一个节点。
        猜你喜欢
        • 2018-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多