我有给定的listitem类:
class Vector
{
public int Column { get; set; }
public int Row { get; set; }
public int TableID { get; set; }
public Vector(int column, int row, int tableID)
{
TableID = tableID;
Row = row;
Column = column;
}
}
后来我有这个项目的类型列表,我想知道给定的向量(列,行,表)是否已经添加到此列表中。当然是微不足道的解决方案:
var items = new List<Vector>();
items.Add(new Vector(1, 2, 3));
items.Add(new Vector(5, 6, 7));
for (int i = 0; i < 1000; i++)
{
if (items.Any(e => e.Column == 1 && e.Row == 2 && e.TableID == 3))
{
// do something
}
}
是的它有效,但是......我担心,随着列表中的项目越来越多,它会指数变慢,因为你必须枚举所有项目才能找到匹配的项目。
最后我的问题是:
您能推荐其他数据结构以允许“快速包含”吗?我的意思是至少线性算法。任何人都会这样做,我只需要存储3个相关的int并稍后检查包含。
答案 0 :(得分:5)
您可以为您的类实现IEquatable<T>
接口(方法public bool Equals(T other)
和public override int GetHashCode()
)并使用HashSet存储唯一项:
class Vector : IEquatable<Vector>
{
/*Some fields and methods*/
public bool Equals(Vector other)
{
if (ReferenceEquals(other, null)) return false;
if (ReferenceEquals(this, other)) return true;
return Column.Equals(other.Column) && Row.Equals(other.Row) && TableID.Equals(other.TableID);
}
public override int GetHashCode()
{
return Column.GetHashCode() ^ Row.GetHashCode() ^ TableID.GetHashCode();
}
}
并使用hashset:
var set = new HashSet<Vector>();
var vect = new Vector { ... };
set.Add(vect);
答案 1 :(得分:2)
您能否推荐其他数据结构以允许“快速包含”?
由于所有向量都必须是唯一的,因此您可以使用HashSet<Vector>
并实施相应的方法GetHashCode
和Equals
:
class Vector
{
public int Column { get; set; }
public int Row { get; set; }
public int TableID { get; set; }
public Vector(int column, int row, int tableID)
{
TableID = tableID;
Row = row;
Column = column;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + Column.GetHashCode();
hash = hash * 23 + Row.GetHashCode();
hash = hash * 23 + TableID.GetHashCode();
return hash;
}
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Vector)) return false;
Vector v2 = (Vector)obj;
return Column == v2.Column && Row == v2.Row && TableID == v2.TableID;
}
}
在我看来,这应该足够快。
HashSet<Vector> items = new HashSet<Vector>();
bool isNew = items.Add(new Vector(1, 2, 3));
isNew = items.Add(new Vector(5, 6, 7));
isNew = items.Add(new Vector(5, 6, 7)); // false
答案 2 :(得分:1)
这听起来接近System.Collections.Generic.HashSet
的完美用例(如果您使用的是.Net 4.0或更高版本)。
你需要在你的类上实现IEquatable,并且对你的GetHashCode实现要小心一点,因为三个组件的简单xor可能会导致大量的哈希冲突,例如第1行第2行和第2行同一个表中的第1列总是会发生碰撞;请查看CRC32算法,了解如何更好地完成它。
或者,实现相同结果的快捷方法是使Vector
继承自Tuple<int, int, int>
,并将友好命名属性作为Item1
的代理, Item2
和Item3
- 微软已经开始担心实现良好的哈希值。
答案 3 :(得分:0)
一种方法是从值构造密钥或散列,并使用它将向量存储在散列表中。
另一种方法是对数组进行排序,然后使用包含的二进制方法,为contains方法提供log(n)而不是线性n。
答案 4 :(得分:0)
您可以尝试使用哈希表,如果正确实现访问时间是常量(在完美世界中)或使用有序二叉树,查找值的最大步骤数是log base 2 n其中n是数字元素,并且对数的结果被四舍五入,在现实生活中它的大部分时间比日志结果更少的步骤,如果这是正确实现并且你有一个平衡的二叉树,那么这是真的
哈希表比二叉树更快但实现更难,所以由你来决定