数据结构/算法,可以跟踪结构(x和y)和值,避免重复

C++ - Data structure/algorithm that can keep track of structures (x and y) and values avoiding duplicates

本文关键字:和值 算法 跟踪 数据结构 结构      更新时间:2023-10-16

我正在寻找一个数据结构用于我正在工作的程序。它跟踪x和y值,并且只有当x,y位置不是我的数组时才需要设置Z。

我尝试使用动态数组,随着列表的增长,迭代数据变得非常非常慢。下面是我的结构。

struct pos{int x;int y;}

对应的值是一个整数,只有当x,y对不存在时才会设置。

编辑:我一直在尝试使用地图,但无法弄清楚如何使用x, y坐标有索引,即如何插入(pos, zValue);

您可以使用map,或者如果您使用c++ 11编译器,则使用unordered_map来保存点的索引

详细说明如何插入到std::map<std::pair<int, int>, int> xy_to_z_mapping;

std::pair<std::pair<int, int>, int> point(int x, int y, int z) {
    return std::make_pair(std::make_pair(x,y),z);
}
xy_to_z_mapping.insert(point(x,y,z));

xy_to_z_mapping.insert(std::make_pair(std::make_pair(x,y),z));

xy_to_z_mapping[std::make_pair(x,y)] = z;

正如andre所说,要避免在结构体上重载操作符,可以使用以下映射:

std::map<std::pair<int, int>, int> a_map;

插入:

插入a_map.insert(std::pair<std::pair<int,int>, int>(std::pair<int,int>(x, y), z));

std::pair<int, int> index(x, y); a_map[index] = z;

或(最简洁的版本,借用andre的回答)

a_map[make_pair(x, y)] = z;

访问:

如果你只是遍历元素,而不是特别关心通过它们的索引访问值,这种方法是很好的。如果你do想要这样做,那么你可以像这样访问它们:

std::pair<int, int> index(x, y); int z = a_map[index];

或(最新版本)

int z = a_map[make_pair(x, y)];

您也可以使用find(),但同样,您需要为它构建一个pair (http://www.cplusplus.com/reference/map/map/find/)。

您可以使用<utility> (http://www.cplusplus.com/reference/utility/make_pair/)中的make_pair()函数使构造对更容易一些,但如果您不想使用带有成对的映射作为索引,那么您可能需要恢复到原始计划并使用std::map<pos, int>代替。

选择地图:

如果您决定使用std::map<pos, int>,请记住在pos上重载operator<,以允许map对其键进行排序(因为您实际上没有使用任何排序功能,您可以任意返回pos::xpos::y的比较)。

无序地图:

如果你想完全避免重载操作符和排序,你可以使用新的c++ 11 unordered_map,它是一个更有效的插入和删除容器。由于您只使用map的惟一性和迭代器属性,如果可以的话,值得考虑使用unordered_map(它们具有非常相似的接口,并且我之前通过更改变量的类型来使用它们代替map !)

我多少认为正确的数据结构应该是一个集合,而不是一个映射。原因是,如果您正在处理Point s或Position s,则数据类型包含三个坐标(x, yz)。

现在,您似乎有兴趣更新Positionz -坐标,只有当具有相同x -和y -坐标的另一个点尚未更新时。

我使用一个无序集合创建了以下实现。注意,散列器和比较器只使用xy

#include<iostream>
#include<unordered_set>
template<typename T>
struct Position {
  Position(T x, T y, T z)
      : x(x),
        y(y),
        z(z) {}
  T x, y, z;
};
template<typename T>
std::ostream& operator<<(std::ostream& os, const Position<T>& p) {
  os<<"("<<p.x<<", "<<p.y<<", "<<p.z<<")";
  return os;
}
struct point_equal {
  template<typename T>    
  bool operator()(const Position<T>& p1, const Position<T>& p2) const {
    return (p1.x == p2.x) && (p1.y == p2.y);
  }
};
struct point_hash {
  template<typename T>    
  std::size_t operator()(const Position<T>& p) const {
    std::hash<T> hasher;
    return hasher(p.x) ^ hasher(p.y);
  }
};
template<typename T>
class Particles {
 public:
  bool add(T x, T y, T z) {
    return m_particles.emplace(x, y, z).second;
  }
  void show() const {
    for(auto p : m_particles) {
      std::cout<<p<<std::endl;
    }    
  }
 private:
  typedef std::unordered_set<Position<T>, point_hash, point_equal> Container;
  Container m_particles;
};

int main() {
  Particles<int> p;
  std::cout<<std::boolalpha;  
  std::cout<<"should show (1, 2, 3)"<<std::endl;
  std::cout<<"Added new point? "<<p.add(1, 2, 3)<<std::endl;  
  p.show();
  std::cout<<"should show (1, 2, 3) again"<<std::endl;
  std::cout<<"Added new point? "<<p.add(1, 2, 4)<<std::endl;
  p.show();
  std::cout<<"should show (1, 2, 3) and (3, 4, 5)"<<std::endl;
  std::cout<<"Added new point? "<<p.add(3, 4, 5)<<std::endl;  
  p.show();
  std::cout<<"should show (1, 2, 3) and (3, 4, 5) again"<<std::endl;
  std::cout<<"Added new point? "<<p.add(3, 4, 9)<<std::endl;    
  p.show();
  return 0;
}

g++ example.cpp -std=c++11编译(使用GCC 4.7.2)我得到以下结果:

should show (1, 2, 3)
Added new point? true
(1, 2, 3)
should show (1, 2, 3) again
Added new point? false
(1, 2, 3)
should show (1, 2, 3) and (3, 4, 5)
Added new point? true
(3, 4, 5)
(1, 2, 3)
should show (1, 2, 3) and (3, 4, 5) again
Added new point? false
(3, 4, 5)
(1, 2, 3)