[英]Which is best data structure for searching and counting of pairs of objects in vector of vectors
我已经定义了class element
和class node
。
类元素
class element
{
int id;
std::vector<node> m_nodes; // An element consist of 4 nodes.
public:
getnode(int) // return n-th node;
}
类节点
class node
{
int id;
// other members
}
class model
由整个node
和element
对象组成。 class element
对象由四个node
对象的向量组成。 一对两个连续(相邻)的node
对象称为面。
例:
elem1:{1,2,3,4}
elem2:{3,5,6,4}
elem1和elem2是两个element
对象,数组中的整数表示四个节点对象的id。
1-2、2-3、3-4和4-1是elem1的面孔。 3-5、5-6、6-4和4-3是elem2的面孔。 面3-4和面4-3是相同的,因此由两个元素共享 。
边界元素是由至少一个面组成的元素,其他元素不共享。 在上面的示例中,elem1和elem2都是边界元素。 边界元素的向量也在模型类中定义。
类模型
class model
{
std::vector<node> m_nodes;
std::vector<element>m_elements;
std::vector<element>m_boundary;
public:
void set_boundary_elements();
}
问题:如何初始化边界元素的向量
这是set_boundary_elements()函数的伪代码。
void model::set_boundary_elements()
{
std::vector <std::pair<std::set<int> , int >> faces;
std::set<int> s;
for(auto iter::m_elements)
{
//initialise face.
for(int i=1; i<5; ++i)
{
if(i != 4)
{
s.insert(iter.getnode(i));
s.insert(iter.getnode(i+1));
}
else
{
s.insert(iter.getnode(4));s.insert(iter.getnode(1));
}
for(auto it: faces)
{
if(s== it.first)
(it.second)++; break;
}
faces.push_back(s,1);
}
//then push_back the elements which have nonshared faces, into m_boundary.
}
}
我认为我的算法效率低下,因为每次必须迭代所有面孔时都要添加面孔。 在stl /算法中有什么有用的方法可以有效地解决我的问题吗?
如对您的帖子的评论中所述,将std :: array用于静态大小的向量,并在for循环中使用const引用,这将避免复制并有助于优化:
for (const auto &iter: m_elements)
和
for(auto &it: faces)
如果您有很多元素(> 50),我想您还应该将用于面部的容器从std :: vector更改为std :: map ,这样:
for(auto it: faces)
{
if(s== it.first)
(it.second)++; break;
}
faces.push_back(s,1);
会变成:
auto &it = faces.find(s);
if (it != faces.end())
it.second++;
else
faces.insert(std::make_pair(s, 1));
重新考虑您的设计。 当前,元素并不真正共享节点。 应该共享一个节点的两个元素只是简单地每个都存储恰好具有相同id的一组不同的数据。 这意味着,如果某项更改一个节点,则系统可能会不一致。
这是我的建议(假设您可以轻松地填写这些内容,那么就不需要构造函数,getter,setters等):
class Model {
class Node;
class Element;
private:
vector<Node> nodes;
vector<Element> elements;
}
class Model::Element {
private:
Element(); //only to be created by Model
vector<unsigned int> incident_nodes;
}
class Model::Node {
private:
Node(); //only to be created by Model
vector<unsigned int> incident_elements;
}
请注意,Node和Element都存储事件项,它们使用在Model中向量中引用其ID的整数进行存储。 模型负责创建和修改节点和元素,而此类方法将负责使数据保持一致。 Element或Node上的所有公共方法都是常量。
这样就为您提供了一个稳定的系统,该系统具有双向引用。 如果您想知道元素是否在边界上,则代码为
//returns all entries that are in both vectors
inline vector<unsigned int> intersection(const vector<unsigned int>& vector_a,
const vector<unsigned int>& vector_b);
typedef vector<unsigned int> Face; //defined in model, a pair of node ids
//number = 0..3, returns the corresponding face
Model::Face Model::get_face(const unsigned int element_id,
const unsigned int number);
vector<unsigned int> Model::incident_elements(const Face& face){
return intersection(nodes[face[0]].incident_elements,
nodes[face[1]].incident_elements);
}
bool Model::is_boundary(const unsigned int element_id){
//check if it has a face that is boundary
for (unsigned int i=0; i<4;i++){
Face face = get_face(element_id, i);
if(incident_elements(face).size() == 1){
return true;
}
}
return false;
}
(所有引用的方法和函数应该是不言自明的,Face可以转换为struct或类,也许可以使用Face :: incident_elements {return cross(...);}方法转换,尤其是如果您想在人脸,但由于Face对象可以轻松提取,因此可能是临时的)
尽管当然每个节点都需要存储事件元素向量,但这需要更多的内存,这种方式可以使您进行清理操作。 但我怀疑您是否可以在没有这种情况的情况下有效地工作,尤其是因为我认为您将需要执行更多此类操作。
可以用某种静态大小替换Node和Element中的向量,但是我认为这没什么大不了的,特别是因为它们只能在Model中访问。
该体系结构的缺点是删除效率低下(更改所有ID存储)或在内存中留下漏洞(尽管如果存储了未使用的ID列表,则还算不错)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.