Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在c+中生成唯一ID+; < >从C++中的两个(或更多)短的int中生成唯一ID的最佳方法是什么?我试图唯一地标识图中的顶点。顶点包含两到四个短整数作为数据,理想情况下,ID应该是它们的某种散列。与速度或轻松相比,更喜欢便携性和独特性_C++_Hash - Fatal编程技术网

在c+中生成唯一ID+; < >从C++中的两个(或更多)短的int中生成唯一ID的最佳方法是什么?我试图唯一地标识图中的顶点。顶点包含两到四个短整数作为数据,理想情况下,ID应该是它们的某种散列。与速度或轻松相比,更喜欢便携性和独特性

在c+中生成唯一ID+; < >从C++中的两个(或更多)短的int中生成唯一ID的最佳方法是什么?我试图唯一地标识图中的顶点。顶点包含两到四个短整数作为数据,理想情况下,ID应该是它们的某种散列。与速度或轻松相比,更喜欢便携性和独特性,c++,hash,C++,Hash,这里有很多很好的答案,今晚我将尝试所有答案,看看什么最适合我的问题。再多说几句我在做什么 图表是音频文件中的样本集合。我使用该图作为马尔可夫链,从旧文件生成新的音频文件。由于每个顶点存储几个样本并指向另一个样本,并且样本都是短整数,因此从数据生成ID似乎很自然。把它们组合成一个长的听起来不错,但也许我只需要一个简单的0 1 2 3generateID。不确定需要多少空间来保证唯一性,如果每个顶点存储2个16位样本,则有2^32个可能的组合正确吗?如果每个顶点存储4个样本,那么有2^64个可能的组

这里有很多很好的答案,今晚我将尝试所有答案,看看什么最适合我的问题。再多说几句我在做什么

图表是音频文件中的样本集合。我使用该图作为马尔可夫链,从旧文件生成新的音频文件。由于每个顶点存储几个样本并指向另一个样本,并且样本都是短整数,因此从数据生成ID似乎很自然。把它们组合成一个长的听起来不错,但也许我只需要一个简单的0 1 2 3
generateID
。不确定需要多少空间来保证唯一性,如果每个顶点存储2个16位样本,则有2^32个可能的组合正确吗?如果每个顶点存储4个样本,那么有2^64个可能的组合


特定于库和平台的解决方案与此问题并不真正相关。我不希望任何其他可能编译我的程序的人不得不下载额外的库或更改代码以适应他们的操作系统

要保证ID是唯一的,唯一的方法就是让ID组合比从中获取ID的组合更多

例如,对于2个短裤(假设为16位),您应该使用32位int

int ID = ((int)short1 << 16) | short2;

这还可以让您向每个顶点添加更多/不同的数据。但是,如果希望在不重置的情况下创建超过2^32个顶点,这可能不是最好的方法。

使用long-long以便可以存储所有4种可能的顶点,然后对每个顶点进行位移:


((long long)shortNumberX)一个简单的解决方案是使用64位整数,其中较低的16位是第一个顶点坐标,接下来的16位是第二个顶点坐标,依此类推。这对于所有顶点都是唯一的,尽管不是非常紧凑

所以这里有一些半途而废的代码来做这件事。希望我的演员选对了

uint64_t generateId( uint16_t v1, uint16_t v2, uint16_t v3, uint16_t v4)
{ 
   uint64_t id;
   id = v1 | (((uint64_t)v2) << 16) | (((uint64_t)v3) << 32) | (((uint64_t)v4) << 48);
   return id;
}
uint64生成ID(uint16生成v1、uint16生成v2、uint16生成v3、uint16生成v4)
{ 
uint64_t id;

有时最简单的事情效果最好

你能不能给顶点对象添加一个id字段,然后按构造顺序给它赋值

static int sNextId = 0;
int getNextId() { return ++sNextId; }

即兴我会说使用质数

id = 3 * value1 + 5 * value2 + .... + somePrime * valueN
请确保您的id空间不会溢出(long?long long?)。因为您有固定数量的值,所以只需丢弃一些随机素数即可。不要费心生成它们,列表中有足够的可用值让您继续使用一段时间


不过,我对证明有点粗略,也许有更数学的人可以帮我介绍一下。可能与数字的唯一素数分解有关。

如果您喜欢可移植性,那么很好:

您需要一个包含4项的元组:

typedef boost::tuple<uint16,uint16,uint16,uint16> VertexID;
boost元组已经支持比较、相等等功能,因此很容易在容器和算法中使用。

问题中“ID”的定义并不明确:是否需要将其用作快速顶点查找的键?您可以为
std::map
定义一个比较器(参见下面的示例)

您是否需要能够区分具有相同坐标(但在另一个字段中不同)的两个顶点对象?定义一些“id工厂”(cfr.singleton模式),该工厂生成例如一个整数序列,与顶点对象的值无关。-这与Fire Lancer的建议非常相似(但要注意线程安全问题!)

在我看来,两个具有相同坐标的顶点是相同的。那么,为什么你甚至需要一个额外的ID呢

一旦您在此类型上定义了“”,就可以将其用作例如
std::map
中的键

struct Vertex {
  typedef short int Value;
  Value v1, v2;

  bool operator<( const Vertex& other ) const {
    return v1 < other.v1 || ( v1 == other.v1 && v2 < other.v2 ) ;
};

Vertex x1 = { 1, 2 };
Vertex x2 = { 1, 3 };
Vertex y1 = { 1, 2 }; // too!

typedef std::set<Vertex> t_vertices;

t_vertices vertices;
vertices.insert( x1 );
vertices.insert( x2 );
vertices.insert( y1 ); // won't do a thing since { 1, 2 } is already in the set.

typedef std::map<Vertex, int> t_vertex_to_counter;
t_vertex_to_counter count;
count[ x1 ]++;
assert( count[x1] == 1 );
assert( count[y1] == 1 );
count[ x2 ]++;
count[ y1 ]++; 
assert( count[x1] == 2 );
assert( count[y1] == 2 );
struct顶点{
typedef短int值;
值v1,v2;

bool操作符如果你在Windows上,你可以使用API,在Linux上你可以使用/proc/sys/kernel/random/uuid,你还可以查看“libuuid”。

如果你正在构建一个散列表来存储顶点,我可以想出几种方法来避免冲突:

  • 直接从输入数据生成ID而不丢弃任何位,并使用一个足够大的哈希表来容纳所有可能的ID。对于64位ID,后者将是非常有问题的:您将不得不使用一个比您的ID范围小的表,因此您将不得不处理冲突。即使使用32位ID,您也可以需要超过4GB的RAM才能在没有碰撞的情况下完成
  • 在读取顶点时按顺序生成ID。不幸的是,这使得搜索以前读取的顶点以更新其概率非常昂贵,因为顺序ID生成器不是哈希函数。如果用于构造马尔可夫链的数据量明显小于马尔可夫链用于生成(或者如果两者都很小),这可能不是问题
  • 或者,您可以使用哈希表实现为您处理冲突(例如/),并集中精力处理应用程序的其余部分。

    尝试使用以下方法:

    int generateID()
    {
        static int s_itemID{ 0 };
        return s_itemID++; // makes copy of s_itemID,
                             increments the real s_itemID, 
                             then returns the value in the copy
    }
    

    这来自于。

    实现您自己的哈希可能会很乏味,并且容易出现一些问题,这些问题在您已经推出或部分推出系统时很难调试和解决。windows API中已经提供了一个更好的唯一ID实现。您可以查看更多详细信息


    使用and the总是会导致低8位全部为0。应该将其移位16位,然后进行OR运算。我真的认为联合会提供一种更干净的方法来实现这一点,但这是一个品味问题。仅供参考,使用联合键入这样的双关语是未定义的行为。OP提出了一个不同的问题:如何生成给定2的唯一ID还是4号
    struct Vertex {
      typedef short int Value;
      Value v1, v2;
    
      bool operator<( const Vertex& other ) const {
        return v1 < other.v1 || ( v1 == other.v1 && v2 < other.v2 ) ;
    };
    
    Vertex x1 = { 1, 2 };
    Vertex x2 = { 1, 3 };
    Vertex y1 = { 1, 2 }; // too!
    
    typedef std::set<Vertex> t_vertices;
    
    t_vertices vertices;
    vertices.insert( x1 );
    vertices.insert( x2 );
    vertices.insert( y1 ); // won't do a thing since { 1, 2 } is already in the set.
    
    typedef std::map<Vertex, int> t_vertex_to_counter;
    t_vertex_to_counter count;
    count[ x1 ]++;
    assert( count[x1] == 1 );
    assert( count[y1] == 1 );
    count[ x2 ]++;
    count[ y1 ]++; 
    assert( count[x1] == 2 );
    assert( count[y1] == 2 );
    
    int generateID()
    {
        static int s_itemID{ 0 };
        return s_itemID++; // makes copy of s_itemID,
                             increments the real s_itemID, 
                             then returns the value in the copy
    }