【问题标题】:Copy elements from vector based on condition C++根据条件 C++ 从向量中复制元素
【发布时间】:2015-05-29 20:48:57
【问题描述】:

我正在使用 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;

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

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

【问题讨论】:

    标签: c++ automata


    【解决方案1】:

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

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

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

    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 之后,您需要将每个项目复制的现在存在于两个地方——即groupP 中有一个元素,groupQ 中有一个元素。任何一个都可以修改,但它们是相互独立的,因此可以修改其中任何一个,但对其中一个的修改对另一个没有影响。

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

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

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

    【讨论】:

    • 最佳答案!如果我这样做怎么办:` for(int j=0; jfinal) groupF.push_back(new node(automata[j]-> state_name, automata[j]->transitions, automata[j]->final, automata[j]->initial)); //...等`编辑:抱歉,我无法以代码格式的样式发布它
    • @woz:你当然可以单独动态地分配每个元素——但它容易出错并且通常很慢,所以我倾向于避免它作为一项规则。
    【解决方案2】:

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

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

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

    请注意,像您这样操作原始指针很容易出错,例如,您可能希望使用 shared pointers

    编辑:添加缺少的std::back_inserter

    【讨论】:

    • 你可能想使用std::back_inserter
    猜你喜欢
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-02
    相关资源
    最近更新 更多