基于条件从vector复制元素



我正在使用c++创建Hopcroft的DFA最小化算法。

Hopcroft算法的一部分是-初始-划分两个集合(p有接受和不接受状态,Q只有不接受状态)。我已经有了P组,我试图从P中提取Q.我使用以下代码来做:

for(int i=0; i<groupP.size(); i++)
    if(groupP[i]->final)
        groupQ.push_back(groupP[i]);

,其中groupP和groupQ为:

vector<node*> groupQ;
vector<node*> groupP;

and node是我创建的一个结构,用来表示自动机的一个节点。它保证布尔属性"final"已经被正确设置(非最终状态为false,最终状态为true)。

最后,我的问题是:通过我所做的,将一个元素从向量复制到另一个元素是正确的吗?如果我修改了从groupP复制的元素的内容,是否也会在groupQ中修改相同的元素?

现在,你有指针的向量。从一个向量复制到另一个向量时,复制的是指针,而不是元素本身。

由于有两个指针指向同一个节点,因此对一个节点所做的任何修改都将在另一个组中可见。,如果您更改了groupP[i]->foo,那么同样的更改将在groupQ[j]->foo中可见(前提是groupP[i]是您从groupP复制到groupQ的元素之一)。

如果你不想这样,你有几个选择。一种方法是将groupPgroupQ保留在同一个vector中,但是根据元素的final成员的状态划分vector:

auto P_end = std::partition(groupP.begin(), groupQ.end(), 
                              [](node *n) { return n->final;});

则[groupP.begin(), P_begin)是groupP(即final==true), [P_begin, groupP.end())是groupQ(即final==false)。

这将指针四处移动(并为您提供一个迭代器,以便您知道两者之间的分界线),因此每个元素只有一个指针,但它们被分为两个相关的组。

作为最后一种可能性,您可能想要实际地将元素从groupP复制到groupQ,并在此过程中创建一个新元素,因此,在将项目从groupP复制到groupQ之后,您复制的每个项目现在存在于两个地方-即。在groupPgroupQ中各有一个元素。其中任何一个都可以被修改,但是它们彼此是分开的,所以任何一个都可以被修改,但是对其中一个的修改对另一个没有影响。

实现这一目标最明显的方法是使用节点向量:

vector<node> groupQ;
vector<node> groupP;

这样,当您从一个组复制到另一个组时,您复制的是节点本身,而不是指向节点的指针,因此每次复制都会创建一个与现有节点具有相同值的新的独立节点。

你可以使用std::copy_if来做同样的事情:

std::copy_if(groupP.cbegin(), groupP.cend(),
             std::back_inserter(groupQ),
             [](node* n){ return n->final; });

由于操作的是指针,因此元素本身是共享的,因此在一个容器中修改节点可以从另一个容器中看到。

请注意,像您这样操作原始指针是非常容易出错的,您可能希望使用共享指针。

编辑:

添加丢失的std::back_inserter

最新更新