C# 如何散列三维索引?

C# 如何散列三维索引?,c#,arrays,hash,multidimensional-array,hashtable,C#,Arrays,Hash,Multidimensional Array,Hashtable,我正在尝试将一个由3个整数组成的坐标转换成一个整数(或类似的整数),我可以用它作为字典的键,也可以将磁盘上的数据与程序中的坐标轻松关联起来。我的三维坐标系为负值,没有设置边界 我一直在研究散列。我对这个概念基本上是陌生的,但据我所知,这是一个正确的方向。有人能提出一个好的算法或方法吗?任何将任意3d坐标编码为唯一、无冲突id的方法都会让我走上正确的道路。根据定义,你不能将3个任意整数的元组散列为一个唯一整数(这就像试图将每个96位整数映射为一个唯一的32位整数值),因此你无法使它“无冲突”。然而

我正在尝试将一个由3个整数组成的坐标转换成一个整数(或类似的整数),我可以用它作为字典的键,也可以将磁盘上的数据与程序中的坐标轻松关联起来。我的三维坐标系为负值,没有设置边界


我一直在研究散列。我对这个概念基本上是陌生的,但据我所知,这是一个正确的方向。有人能提出一个好的算法或方法吗?任何将任意3d坐标编码为唯一、无冲突id的方法都会让我走上正确的道路。

根据定义,你不能将3个任意整数的元组散列为一个唯一整数(这就像试图将每个96位整数映射为一个唯一的32位整数值),因此你无法使它“无冲突”。然而,散列算法只需要生成分布良好的值。一个非常简单的算法是对3个整数进行异或运算:

var hash = x ^ y ^ z;
此哈希的一个问题是,它为(1,0,0)提供的值与(0,1,0)的值相同。更好的方法可能是:

var hash = unchecked(x + (31 * y) + (31 * 31 * z));

散列函数可以是简单的,也可以是非常复杂的。大多数情况下,对于像将自定义类型放入字典这样的事情,像上面描述的那样快速、简单的散列函数可以很好地工作。

我想知道您是否考虑过这一点。作为带分隔符的字符串连接的3个坐标应足够唯一,可以用作键。这样做的优点是,如有必要,可以从关键点提取坐标:

    public static string MakeKey(int a, int b, int c)
    {
        return a.ToString() + "/" + b.ToString() + "/" + c.ToString();
    }
回复:OP的评论:

不确定您所指的数据量,但这里有一些代码需要考虑。这使得一个字典有1000万个条目,每个键是一个30个字符长的随机字符串,并将这些字符串的随机数量放入一个列表中。我做的一个测试在11毫秒内从字典中提取了13000个条目:

        Dictionary<string, int> test1 = new Dictionary<string, int>();
        Random rnd = new Random();
        int stopint = rnd.Next(2, (int)(Math.Sqrt(10000000)/2));
        List<string> check = new List<string>();
        for(int i = 0; i < 10000000; i++)
        {
            StringBuilder sb = new StringBuilder();
            for(int j = 0; j < 30; j++)
            {
                sb.Append((char)rnd.Next(33, 256));
            }
            if(i % stopint == 0)
            {
                check.Add(sb.ToString());
                stopint = rnd.Next(2, (int)(Math.Sqrt(10000000) / 2));
            }
            test1.Add(sb.ToString(), i);
        }

        for(int i = 0; i < check.Count; i++)
        {
           int test = test1[check[i]];
        }
Dictionary test1=newdictionary();
随机rnd=新随机();
int stopint=rnd.Next(2,(int)(数学Sqrt(10000000)/2));
列表检查=新列表();
对于(int i=0;i<10000000;i++)
{
StringBuilder sb=新的StringBuilder();
对于(int j=0;j<30;j++)
{
sb.Append((char)rnd.Next(33256));
}
如果(i%stopint==0)
{
检查添加(sb.ToString());
stopint=rnd.Next(2,(int)(数学Sqrt(10000000)/2));
}
test1.Add(sb.ToString(),i);
}
for(int i=0;i
请注意,您不需要散列到唯一的值。对于
Dictionary
来说,散列值均匀分布更为重要。为什么不重写Equals和GetHashCode并将键作为类对象本身呢。这里的类对象是表示3d点的实例。在GetHashCode中,使用Chase提供的代码。在Equals中,只需检查两个点x,y,z的相等性,就可以将三元组转换成字符串并对字符串进行散列。谢谢您的解释。这正是我所需要的,让我超越基本理解的门槛。我是这个论坛的新成员,所以还不能投票,但我非常感谢。我把它标为答案。如果有人有一个适合我描述的案例的奇特算法,我很乐意接受它:)好主意。但我主要关心的是基于字符串的键的大小和比较速度。我正在处理非常大的数据集,这种方法可能会很昂贵。我希望生成可以快速比较的紧凑密钥。为了澄清一点,我正在实时上下文中处理数百万条条目。我不断地在RAM和磁盘之间移动数据。这就是尺寸成为重要考虑因素的地方。