如何递归"print list from tail to head"?

How to "print list from tail to head" recursively?

本文关键字:tail from to head list print 递归 何递归      更新时间:2023-10-16

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

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);
*/
}
};

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

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; 
}
}

你的函数不输出任何内容。使用向量递归输出列表是一个坏主意。

例如,该函数可以按以下方式查找,如下面的演示程序所示。

#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 

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

#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;
}

我正在尝试使用 递归

因为您没有提供有关列表的信息,所以在这里我将向您展示使用"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  << "nn" << endl;
return 0;
}
void recurseAndReportSize()
{
if (0 == m_strList.size()) {
cout << "n  empty  list" << flush;
return;
}
cout << "nn  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