【问题标题】:Arrays Vs Vector During Recursion递归期间的数组与向量
【发布时间】:2016-05-15 07:54:22
【问题描述】:

我对下面二叉树代码中的数组和向量有些疑惑。

下面是找到的代码 打印距离叶节点k距离的所有节点

void TraceLeaves(node *temp,int k,vector<int> v,vector<int> visited)
{

    if(temp->left==NULL&&temp->right==NULL)
    {
        v.push_back(temp->data);

        if(visited[v.size()-k-1]==0)
        {
            visited[v.size()-k-1]=1;
            cout<<v[v.size()-k-1]<<"\n";
        }

        return;
    }
    else
    {
        v.push_back(temp->data);
        visited.push_back(0);
    }

    TraceLeaves(temp->left,k,v,visited);

    TraceLeaves(temp->right,k,v,visited);

}

int main()
{
    root = createnode(1);
    root->left=createnode(2);
    root->right=createnode(3);
    root->left->left = createnode(4);
    root->left->right = createnode(5);
    root->right->left = createnode(6);
    root->right->right = createnode(7);
    vector<int> v;
    vector<int> visited;
    TraceLeaves(root,1,v,visited);
}

上述方法的输出是

2
2
3
3

当我将 vectorvisited 数组替换为 boolvisited[]

喜欢

void TraceLeaves(node *temp,int k,vector<int> v,bool visited[])
{

    if(temp->left==NULL&&temp->right==NULL)
    {
        v.push_back(temp->data);

        if(visited[v.size()-k-1]==0)
        {
            visited[v.size()-k-1]=1;
            cout<<v[v.size()-k-1]<<"\n";
        }

        return;
    }
    else
    {
        v.push_back(temp->data);
        visited[v.size()-1]=0;
    }

    TraceLeaves(temp->left,k,v,visited);

    TraceLeaves(temp->right,k,v,visited);

}

int main()
{
    root = createnode(1);
    root->left=createnode(2);
    root->right=createnode(3);
    root->left->left = createnode(4);
    root->left->right = createnode(5);
    root->right->left = createnode(6);
    root->right->right = createnode(7);
    vector<int> v;
    bool visited[5]={false};
    TraceLeaves(root,1,v,visited);
}

我得到了

2
3

这其实是正确的..

所以我在网上搜索..告诉我

void TraceLeaves(node *temp,int k,vector<int> v,vector<int> visited)

应该替换为

void TraceLeaves(node *temp,int k,vector<int> v,vector<int> &visited)

这次改动后的完整是

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int data;
    struct node *left;
    struct node *right;
}*root;

node* createnode(int d)
{
    node *New;
    New = new node;
    New->data = d;
    New->left=NULL;
    New->right=NULL;
}

void TraceLeaves(node *temp,int k,vector<int> v,vector<int>& visited)
{

    if(temp->left==NULL&&temp->right==NULL)
    {
        v.push_back(temp->data);

        if(visited[v.size()-k-1]==0)
        {
            visited[v.size()-k-1]=1;
            cout<<v[v.size()-k-1]<<"\n";
        }

        return;
    }
    else
    {
        v.push_back(temp->data);
        visited.push_back(0);
    }

    TraceLeaves(temp->left,k,v,visited);

    TraceLeaves(temp->right,k,v,visited);

}

int main()
{
    root = createnode(1);
    root->left=createnode(2);
    root->right=createnode(3);
    root->left->left = createnode(4);
    root->left->right = createnode(5);
    root->right->left = createnode(6);
    root->right->right = createnode(7);
    vector<int> v;
    vector<int> visited(5,0);
    TraceLeaves(root,1,v,visited);
}

但它给了我输出

2

因为我们通过引用使用数组意味着更改将被更新

2 ,3 处于同一级别。所以只有 2 被打印出来。

所以我的问题是

为什么在代码中使用 boolvisited[] 并通过引用传递时我得到 2,3 作为输出,而当使用向量 &v 时只得到 2 ??

提前致谢。

【问题讨论】:

  • visited.push_back(0)bool visited[] 怎么做(保持相同的指针)?
  • visited[v.size()-1]=0 因为我们只需要在末尾添加。
  • 仅仅push_back 增加条目数的大小,而数组不能调整大小的事实就足以改变使两个代码示例都不同。如果您将向量的大小设置为与前面的数组相同,那么将(或应该)没有区别。
  • visited[v.size()-1]=0 -- 可以替换为更直观的visited.back() = 0;
  • 这里我得到了不同的向量输出。你能告诉我如何在向量的帮助下获得 2,3 输出吗?如果我使用按引用传递意味着它只得到 2 但是当我们通过引用传递布尔数组时,我们得到 2,3

标签: c++ arrays vector binary-tree pass-by-reference


【解决方案1】:

有区别

bool visited[5]={false};

vector<int> visited;

除了明显的 C 样式数组 vs std::vector。在第一种情况下,数组正好有 5 个元素,全部用 false 初始化。在第二种情况下,向量是空的,并且您没有在任何地方插入任何东西(至少在您显示的代码中没有)。因此,在这种情况下,当您在该函数中访问 visited[v.size()-k-1] 时,您正在尝试读取和更改不存在的元素,这是未定义的行为。

要在使用 std::vector 时获得相同的行为,您应该在使用之前使用相同的元素对其进行初始化。

【讨论】:

  • 其实visited[v.size(0-k-1]只在叶子节点被引用。所以在到达叶子节点之前,visited数组会插入一些元素。[查看else块]所以这没有问题。
【解决方案2】:

请注意:

您的 createNode 函数中有未定义的行为。您没有返回值,但该函数应该返回node*。在继续之前,您需要解决此问题。


首先,您必须意识到您发布的两个示例根本不同,不仅仅是因为您在第一个示例中使用了向量,然后在第二个示例中使用了数组。

首先,数组不能调整大小。因此,当visited 是一个向量时,您的第一个示例会这样做:

 visited.push_back(0); // resizes

这是该行与该行之间的主要区别(在您的数组示例中):

 visited[v.size()-1]=0;  // does not resize 

所以我们本可以在这两个示例中的不同之处停下来。然而,这里有另一个区别:

void TraceLeaves(node *temp,int k,vector<int> v,vector<int> visited)

这里,visited 是一个按值传递的向量。这意味着 TraceLeaves 中发生在 visited 向量上的任何更改都是本地的,不会反射回调用者。

在您的数组示例中将其与此进行比较:

void TraceLeaves(node *temp,int k,vector<int> v,bool visited[])

visited 参数是bool *[] 语法并没有改变这一事实。所以上面的声明就是这样的:

void TraceLeaves(node *temp,int k,vector<int> v,bool* visited)

这与上面的vector 版本非常不同。您在这里所做的是传递一个指向visited 的指针,因此您对visited“数组”所做的更改会反映给调用者。


如果您真的希望两个示例相同,则必须将它们编写为相同,而不是不同。首先,将向量的大小调整为与数组示例相同的大小。在main:

std::vector<bool> visited(5,false);

那么TraceLeaves 函数看起来完全与数组示例相同,不同之处在于模仿指针示例的函数原型:

void TraceLeaves(node *temp,int k,vector<int> v,vector<int>& visited)

Live Example with changes described above

【讨论】:

  • 我对向量代码做了这两处改动,vectorvisited(5,0);和 void TraceLeaves(node *temp,int k,vector v,vector&visited) 但我仍然只得到 2 作为输出。如帖子中所述,我已经通过引用检查了传递向量: )
  • 现在我把完整的代码放在帖子里了。检查一次:)
  • @sai 查看我的更新。您应该修复您的 createNode 函数,因为它没有返回值。
  • @sai 请仔细阅读我的回答。当你不应该打电话时,你仍在打电话给push_back。您使用向量的代码应该完全与数组版本相同。这意味着您也应该这样做:visited[v.size() - 1] = 0; 在数组版本中 在矢量版本中。唯一的区别是向量通过引用传递给您的函数,并且在调用之前向量的大小必须为 5。一旦你这样做了,那么你将拥有等效的代码。
  • 非常感谢 :) :) @PaulMcKenzie 指出我的错误。有效。我还发现了不同的方法,例如,首先保留一个空向量,通过引用传递它,现在您可以使用visited.push_back(0) 但在代码末尾,您还应该放置visited.pop_back() 否则0 将留在即使移动到另一条路径,向量也是如此。 :) :)
猜你喜欢
  • 2015-03-08
  • 2021-11-13
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-13
  • 2010-12-28
  • 2015-06-20
相关资源
最近更新 更多