【问题标题】:How to "print list from tail to head" recursively?如何递归地“从头到尾打印列表”?
【发布时间】:2020-01-01 19:07:39
【问题描述】:

我正在尝试使用递归从尾到头打印链表中的每个节点。但是为什么我不能使用高亮代码来实现递归呢?

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        if(!head)
        {
            vector<int> a(0);
            return a;
        }
        else if(!head -> next)
        {
            vector<int> a(1, head -> val);
            return a;
        }
        else
/*
            return printListFromTailToHead(head -> next).push_back(head -> val);
*/
    }
};

【问题讨论】:

  • 您是否考虑在每次此函数返回时返回不同的vector&lt;int&gt;
  • 您好,您只是想打印出来?您的代码只返回一个向量并且不打印任何内容。您实际上不需要返回向量。
  • 递归地遍历列表并将打印语句放置在遍历到列表中的下一个节点之后。这将导致程序运行到列表的末尾并在返回的路上开始打印。顺便问一下,vector 是干什么用的?
  • std::vector::push_back 返回无效。你不能马上退货。将printListFromTailToHead返回的向量绑定到一个局部变量,调用push_back,然后返回。
  • @dedecos 有点不正统,但 RVO 应该防止过度复制。

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


【解决方案1】:

如果你想打印,那就打印 - 不要构建矢量。

void printListFromTailToHead(ListNode* head) 
{
    if (head)
    {
        printListFromTailToHead(head->next);
        std::cout << head->val << '\n';
    }
}

如果你真的不想想打印任何东西而只生成一个向量,你需要稍微重新排列一下代码,因为push_back 不返回任何东西:

vector<int> reverse_list(ListNode* head) 
{
    if (!head)
    {
        return vector<int>{};
    }
    else // You don't need a special case for a one-element list.
    {
        vector<int> ls = reverse_list(head->next);
        ls.push_back(head->val);
        return ls; 
    }
}

【讨论】:

    【解决方案2】:

    你的函数什么也不输出。而且使用向量递归输出列表是个坏主意。

    该函数可以如下面的演示程序所示。

    #include <iostream>
    
    struct ListNode
    {
        int value;
        ListNode *next;
    };
    
    void push_front( ListNode * &head, int value )
    {
        head = new ListNode { value, head };
    }
    
    std::ostream & printListFromHeadToTail( ListNode * &head, std::ostream &os = std::cout  )
    {
        return head == nullptr ? os 
                               : ( os << head->value << ' ', printListFromHeadToTail( head->next, os )  );  
    }
    
    std::ostream & printListFromTailToHead( ListNode * &head, std::ostream &os = std::cout  )
    {
        return head == nullptr ? os 
                               : ( printListFromTailToHead( head->next, os ), os << head->value << ' ' );  
    }
    
    int main() 
    {
        const int N = 10;
        ListNode *head = nullptr;
    
        for ( int i = 0; i < N; i++ ) push_front( head, i );
    
        printListFromHeadToTail( head ) << '\n';
        printListFromTailToHead( head ) << '\n';
    
        return 0;
    }
    

    它的输出是

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

    【讨论】:

      【解决方案3】:

      看看这个解决方案,也许不是更好的方法,但你也许可以接受这个想法。问题是,你不需要返回一个数组,我也不明白你为什么要返回一个向量,你可以再次调用该函数,然后像下面的代码一样打印它。

      #include <iostream>
      
      
      using namespace std;
      
      
      class ListNode {
      
      public:
        ListNode *next;
        int value;
      
        ListNode() {
          this->next = NULL;
          this->value = 0;
        }
      
        ListNode(int _v) {
          this->next = NULL;
          this->value = _v;
        }
      };
      
      void printListNodeFromTailToHead(ListNode *node) {
        // If the current node is null will
        // exit the recursive function
        if (node == NULL) return ;
      
        // Else will call the function again with next ListNode
        // and print the current value
      
        printListNodeFromTailToHead(node->next);
        cout << node->value << endl;
      }
      
      
      int main() {
        ListNode *a = new ListNode(1);
        ListNode *tmp = a;
      
        for (int i = 2; i < 10; i++) {
          a->next = new ListNode(i);
          a = a->next;
        }
      
        printListNodeFromTailToHead(tmp);
        return 0;
      }
      

      【讨论】:

      • 很好的答案,但对错误的问题。 OP 想要的是一个从头到尾打印而不是从头到尾打印的功能。当然,很容易修改这个答案来做到这一点,提示,提示。
      【解决方案4】:

      我正在尝试使用从尾到头打印链表中的每个节点 递归

      因为您没有提供有关您的列表的信息,所以在这里我将使用“std::list”向您展示您想要的功能的简单实现。请注意,我提供的递归没有函数参数,没有全局范围变量,也没有静态变量(我使用 cout,而不是 print)。

      另外,我使用一种称为 Functor 的类形式。我推荐它们来封装“小”功能。请查看有关函子的文献……我认为它们比典型的类“简单”。

      #include <iostream>
      using std::cout, std::cerr, std::endl, std::flush; // c++17
      using std::ostream;
      
      #include <list>
      using std::list;
      
      #include <string>
      using std::string, std::to_string;
      
      
      
      // typedefs are often simpler to read
      // user typedefs ---------------vvvvvvvvvvv
      typedef list<string>            StrList_t;
      typedef list<string>::iterator  StrListIt_t;
      
      
      // Functor
      class F820_Recursive_t
      {
         // data attributes of class instance are not global nor static vars
         StrList_t    m_strList;
         StrListIt_t  m_it;
      
      public:
         int operator()() { return exec();  }  // Functor entry
      
      private:
      
         int exec() // builds and modifies a std::list<string>
            {
               // example: using initializer list syntax
               m_strList = StrList_t { "111", "222", "333", "444", "555", "666", "777", "888" };
      
               recurseAndReportSize();
      
               // example: appending to existing list
               for (int i=301; i<309; ++i) {
                  string s = "S" + to_string(i);
                  m_strList.push_back (s);
               }
      
               recurseAndReportSize();
      
               cout << "\n  version cplusplus: " <<  __cplusplus  << "\n\n" << endl;
               return 0;
            }
      
         void recurseAndReportSize()
            {
               if (0 == m_strList.size()) {
                  cout << "\n  empty  list" << flush;
                  return;
               }
      
               cout << "\n\n  recurse over list to count elements ... " << flush;
      
               m_it = m_strList.begin(); // head to tail
               uint count = recurseCount();
      
               // report
               cout << count << " elements" << endl;
      
               // report list contents head to tail
               m_it = m_strList.begin();
               cout << "\n  Head to Tail recursive content report "
                    << "\n  [" << coutListFromHeadToTail() << "]" << endl;
      
               // report list contents  tail to head
               m_it = m_strList.end(); m_it--;
               cout << "\n  Tail to Head recursive content report: "
                    << "\n  [" << coutListFromTailToHead() << "]" << endl;
            }
      
         // recurse with no parameters, no static vars, no global vars
         uint recurseCount( )
            {  //        --^-- no parameters
               if (m_it == m_strList.end()) // RTC (recursion termination clause)
                  return 0;
      
               m_it++; // step to next element
      
               return (1 + recurseCount()); // tail recursion
            }
      
         // recurse with no parameters, no static vars, no global vars
         string  coutListFromHeadToTail ( )
            {                        // --^-- no parameters
               cout << *m_it++;
               if (m_it == m_strList.end()) // RTC (recursion termination clause)
                  return "";
               cout << ", ";
               return coutListFromHeadToTail(); // tail recursion
            }
      
         // recurse with no parameters, no static vars, no global vars
         string  coutListFromTailToHead ( )
            {                       // --^-- no parameters
               if (m_it == m_strList.begin()) {
                  cout << *m_it;
                  return "";
               }
               cout << *m_it << ", ";
               m_it--;
               return coutListFromTailToHead();  // tail recursion
            }
      
      }; // class F820_Recursion_t
      
      int main(int, char**) { return F820_Recursive_t()(); }
      

      在我的 Lubuntu 19.04、g++ v8.3 上输出

        recurse over list to count elements ... 8 elements
      
        Head to Tail recursive content report 
        [111, 222, 333, 444, 555, 666, 777, 888]
      
        Tail to Head recursive content report: 
        [888, 777, 666, 555, 444, 333, 222, 111]
      
      
        recurse over list to count elements ... 16 elements
      
        Head to Tail recursive content report 
        [111, 222, 333, 444, 555, 666, 777, 888, S301, S302, S303, S304, S305, S306, S307, S308]
      
        Tail to Head recursive content report: 
        [S308, S307, S306, S305, S304, S303, S302, S301, 888, 777, 666, 555, 444, 333, 222, 111]
      
        version cplusplus: 201703
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-22
        • 1970-01-01
        • 2017-06-22
        • 2016-05-07
        • 2016-06-23
        • 2020-03-17
        • 1970-01-01
        • 2021-02-18
        相关资源
        最近更新 更多