我使用C ++创建了Hopcroft的DFA最小化算法。
霍普克罗夫特算法的一部分是 - 最初 - 划分两组(P表示接受和非接受状态,Q表示只有非接受状态)。我已经有了P组,并且从P I尝试提取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是我创建的结构,用于表示我的自动机的节点。它保证了布尔属性&#34; final&#34;已经正确设置(对于非最终状态为false,对于最终状态为true)。
最后,我的问题是:通过做我做过的事情,将一个元素从一个向量复制到另一个元素是否正确?如果我从groupP修改复制元素的内容,那么同样的元素也会在groupQ中被修改吗?
答案 0 :(得分:3)
现在,你有指针的向量。当您从一个向量复制到另一个向量时,您将复制指针,而不是元素本身。
由于您有两个指向同一节点的指针,因此对节点所做的任何修改都将在另一个组中可见 - 即,如果您对groupP[i]->foo
进行了更改,则会看到相同的更改在groupQ[j]->foo
中(前提是groupP[i]
是您从groupP
复制到groupQ
的其中一个元素。
如果你不想那样,你有几个选择。一种方法是将groupP
和groupQ
保留在同一个向量中,但根据元素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
复制到{ {1}},您现在复制的每个项目都存在于两个位置 - 即groupQ
中有一个元素,groupP
中有一个元素。任何一个都可以修改,但它们彼此分开,所以要么可以修改,要么修改一个对另一个没有影响。
实现这一目标最明显的方法是使用节点向量:
groupQ
这样,当您从一个组复制到另一个组时,您将复制节点本身而不是指向节点的指针,因此每个副本都会创建一个与现有节点具有相同值的新的独立节点。
答案 1 :(得分:1)
你可以使用std::copy_if做同样的事情:
std::copy_if(groupP.cbegin(), groupP.cend(),
std::back_inserter(groupQ),
[](node* n){ return n->final; });
由于您正在操作指针,因此元素本身是共享的,因此可以从另一个容器中看到修改其中一个容器中的节点。
请注意,像您一样操作原始指针非常容易出错,例如,您可能希望使用shared pointers。
修改:添加缺失的std::back_inserter
。