如何在递归函数中打印向量

How can I print a vector in a recursive function?

本文关键字:打印 向量 递归函数      更新时间:2023-10-16

我这里有一个问题:我要编写一个函数,以递归方式打印向量的元素,因此不允许循环。

我尝试了这段代码,但它在运行时崩溃了:

void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
    if (it == ivec.end())
        return;
    std::cout << *it++ << std::endl;
    print(ivec, it);
}
int main(){
    vector<int> v{
        5, 7, 77, 23, 10, 81
    };
    print(v, v.begin());
}

如果我运行该程序,我会得到断言对话框!?

void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {

ivec参数按值传递。这两个参数都是按值传递的。按值传递意味着在函数内部,这些是原始参数的副本

您的main()调用此递归函数,向其传递其向量和向量的开始迭代器。但是,由于所有参数都是按值传递的,因此函数的每次递归迭代都会将迭代器与完全不同的向量的end()进行比较。未定义的行为。

您显然忘记通过引用传递向量。第一个参数应const std::vector<int> &ivec

当你调用print时,你按值传递向量。这意味着它每次都会创建一个全新的向量,但迭代器仍然来自原始向量。由于迭代器来自不同的向量,因此测试it == ivec.end()总是会失败。

我们可以通过 const 引用传递ivec来解决此问题:

void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it) 
{
    if (it == ivec.end())
        return;
    std::cout << *it++ << std::endl;
    print(ivec, it);
}

代码工作正常!

您必须通过引用传递向量,以避免多个副本,从而保证迭代器仅与同一向量的迭代器进行比较,而不是与其他向量的迭代器进行比较:

void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it) {
    if (it == ivec.end())
        return;
    std::cout << *it++ << std::endl;
    print(ivec, it);
}
int main(){
    vector<int> v{
        5, 7, 77, 23, 10, 81
    };
    print(v, v.begin()); // ok
    vector<int>::iterator it = v.begin();
    auto v2{ v };
    if (it == v.begin())
        cout << "it = v.begin()" << endl;
    if (it == v2.begin()) // causes crash
        cout << "it =v2.begin()" << endl;
}

无需将两个参数传递给打印函数。 如果矢量长度为零,则不打印任何内容。

如果矢量的长度为 1,则打印该元素。

如果矢量的

长度大于 1,则打印不包含最后一个字符的较小矢量(递归(,然后打印最后一个字符。

是的,这将为每个递归创建一个向量的副本,但我想这对我来说更像是递归。 在每个循环上递增指针并不像递归。

#include <iostream>
#include <vector>
void print(const std::vector<int> vec) {
    if (!vec.size())
        return; 
    else {
        print(std::vector<int>(vec.begin(), vec.end() - 1));
        std::cout << " " << *(vec.end() - 1);
    }
}
int main(){
    std::vector<int> v{
            5, 7, 77, 23, 10, 81
    };
    print(v);
}

如果你只需要打印向量,我认为一个更优雅的解决方案是使用迭代器。

#include <iostream>
#include <vector>
using namespace std;
void print_vector(vector<int>::iterator it, const vector<int>::iterator &end)
{
    if(it == end) {
        cout << 'n';
        return;
    }
    cout << *it << " ";
    print_vector(++it, end);
}
int main() {
    vector<int> v = {1,2,3,4,5,6,7,8,9};
    print_vector(v.begin(), v.end());
    return 0;
}

如果您想在其他结构中重用该功能(可能是为了给朋友或老师留下深刻印象(,您可以使用模板。

#include <iostream>
#include <set>
#include <vector>
using namespace std;
template<class TContainer>
void print_structure(typename TContainer::iterator it, const typename TContainer::iterator end)
{
    if(it == end) {
        cout << 'n';
        return;
    }
    cout << *it << " ";
    print_structure<TContainer>(++it, end);
}
int main() {
    vector<int> vi = {1,2,3,4,5,6,7,8,9};
    print_structure<vector<int>>(vi.begin(), vi.end());

    vector<double> vd = {1.2, 3.4, 5.6, 7.8, 9.0};
    print_structure<vector<double>>(vd.begin(), vd.end());
    set<int> si = {10, 10, 10, 10, 20, 20, 20, 20, 30, 30, 30};
    print_structure<set<int>>(si.begin(), si.end());
    set<double> sd = {10.10, 10.10, 20.20, 20.20, 30.30, 3.0};
    print_structure<set<double>>(sd.begin(), sd.end());
    return 0;
}

杀死蚊子看起来像火箭筒吗?果然如此!但这很疯狂是吗?!