【问题标题】:C++: two vectors of pointers to the same structure, each differently sortedC++:指向同一结构的两个指针向量,每个向量的排序不同
【发布时间】:2015-03-26 21:13:27
【问题描述】:

我有一个人的结构类。每个人都有自己的姓名、主要 ID 和次要 ID。为了有效搜索,我实现了二进制搜索。问题是我想有效地(比 O(n) 更好)搜索人不仅通过他们的主要 ID,而且通过他们的次要 ID。但是这些人只能按一个参数排序。所以我想是否有可能制作两个指向persons结构的指针向量,一个按主ID排序,另一个按次要ID排序。

例如,两个人:Mark Smith 的主 ID 为 9845613,辅助 ID 为 1312469,John Doyle,主 ID 为 3213444,辅助 ID 为 2654722。所以 m_byPrim 向量的第一个元素和 m_bySec 向量的第二个元素应该指向 John Doyle。

这可能吗?以下是我目前编写的相关代码的一部分:

#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>

using namespace std;

class CPersons
{
public:
  bool AddPerson (const string &name,
                  unsigned int primID,
                  unsigned int secID);

private:
  struct Person {
    Person (const string & init_name,
            unsigned int init_primID,
            unsigned int init_secID)
     : m_name (init_name), m_primID (init_primID), m_secID (init_secID){}

      string m_name;
      unsigned int m_primID;
      unsigned int m_secID;
  };
  vector<Person*>m_byPrim;
  vector<Person*>m_bySec;
};

bool CPersons::AddPerson (const string &name, 
                          unsigned int primID, 
                          unsigned int secID){

  int positionPrim;
  int positionSec;

  return false;
}

int main ( void )
{
  CPersons a;
  a.AddPerson ( "Mark Smith", 9845613, 1324697 );
  a.AddPerson ( "John Doyle", 3213444, 2654722 );
  return 0;
}

位置整数是我的二进制搜索函数的结果(插入人员的位置),我已经成功地实现了它,所以假设这个位置已经被初始化了。

但我的问题是如何实现指针向量的添加?我对指针(以及一般的 C++)仍然很陌生,所以我不知道我的想法是否有效和可能。感谢您提供任何提示和帮助。

编辑:我忘了提到在 STL 容器中我只能使用向量。

【问题讨论】:

  • 您问:“这可能吗?”。是的,这是可能的。请参阅std::sort 以开始使用。
  • 您所做的与关系数据库在索引不同列时所做的类似。我认为您应该能够在向量上使用insert 将指针放在您需要的位置,但是您可能会从更复杂的结构中获得更好的结果来保存您的排序指针,例如树形图。
  • boost::multi_index 可能会有所帮助。

标签: c++ sorting pointers vector structure


【解决方案1】:

尝试使用 std::map:而不是排序向量:

class CPersons
{
public:
  bool AddPerson (const string &name, unsigned int primID, unsigned int secID);

private:
  struct Person {
    Person (const string & init_name, unsigned int init_primID, unsigned    int init_secID)
      : m_name (init_name), m_primID (init_primID), m_secID (init_secID) {}

      string m_name;
      unsigned int m_primID;
      unsigned int m_secID;
  };
  map<unsigned int, Person*>m_byPrim;
  map<unsigned int, Person*>m_bySec;
};

bool CPersons::AddPerson (const string &name, unsigned int primID, unsigned int secID){

  p = new Person(name, primID, secID);
  m_byPrim[primID] = p;
  m_bySec[secID] = p;

  return false;
}

使用向量的缺点:

  • 如果您在列表末尾以外的任何位置插入人,则向量中的所有内容都必须“冒泡”,被复制到列表中的新位置。
  • 随着向量的增长,需要定期重新分配它,并将整个现有元素集复制到新的底层数组。

使用地图的好处:

  • 向列表中添加新元素的影响很小
  • 用于添加和查找元素的界面比在已排序的向量中查找内容更加方便和易读。

【讨论】:

  • 如果您使用 ID 作为地图的键,为什么还要将它们存储在人体内?您可以将 ID 映射到 string 并保持简单。
  • 感谢您的回答。看来地图确实是一个更好的选择。但不幸的是,从 STL 中我只能使用向量(这意味着没有地图、集合、列表等)但是无论如何感谢您的回答,我会在以后记录这一点。
  • @EMBLEM 如果在别处使用Person,那么让ID和名称都易于访问可能是方便/必要的。
  • @AtlasC1 Person 不能在其他地方使用。它是 CPersons 类的私有成员。
  • @EMBLEM 我所说的其他地方是指除了地图检索之外的任何地方。例如,如果您在CPersons 中添加了一个方法来从给定的主ID 中获取辅助ID,那么简单地返回map[primId].secId 会很方便;
【解决方案2】:

由于您只能使用 vector,因此您的 AddPerson 函数应如下所示:

bool CPersons::AddPerson(
        const string &name, unsigned int primID, unsigned int secID) {
    // I'm assuming that the two functions below binary-search to get
    // the positions where inserting the elements into the arrays would
    // maintain their sorting
    int positionPrim = getPositionPrim();
    int positionSec = getPositionSec();
    Person *person = new Person(name, primID, secID);
    m_byPrim.insert(m_byPrim.begin() + positionPrim, person);
    m_bySec.insert(m_bySex.begin() + positionSec, person);
    return false;
}

您还需要定义一个析构函数,因为您使用的是动态内存:

CPersons::~CPersons()
{
    for (const auto &i: m_byPrim) {
        delete i;
    }


}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-28
    • 2012-02-07
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    相关资源
    最近更新 更多