我有一个现有的(java)应用程序,它为订单簿建模,因为每个订单都是彼此可见的。现在需要在每个订单ACL中放置(实际上是有效的)。
举例说明,假设我有访问组[V-Z]和订单[A-F]
A B C D E F
V 1 0 0 1 1 0
W 0 1 1 0 0 1
X 0 0 0 0 1 1
Y 1 1 0 0 0 1
Z 0 1 0 1 0 0
新订单将可见性指定为W& Y.返回传入订单可以看到的值集的快速方法是什么?
建议的一个实现是将每一行表示为BitSet并执行W |我虽然不知道随着矩阵大小的增加会对性能产生什么影响。
一个很好的但不是必不可少的功能是允许在一个维度上的父子关系,如
A B C D E F
V 1 0 0 1 1 0
W 0 1 1 0 0 1
X-1 0 0 0 0 1 1
X-2 1 0 0 0 1 1
X-3 0 1 0 0 1 1
Y 1 1 0 0 0 1
Z 0 1 0 1 0 0
如果将“W | X”检索为“W | X-1”同样有效,那将是理想的
非常感谢算法方向和/或适当数据结构的任何提示。
答案 0 :(得分:1)
简单的解决方案:
class AccessGroupName { ... }
class Order { ... }
Map<AccessGroupName, Collection<Order>> visibility = new HashMap<AccessGroupName, Collection<Order>>();
addVisibility(AccessGroupName group, Order order) {
Collection<Order> orders = visibilities.get(group);
if (orders == null) {
orders = new ArrayList<Order>();
visibility.put(group, orders);
}
if (!orders.contains(order)) orders.add(order);
}
public Set<Order> getVisibility(Collection<AccessGroupName> names) {
Set<Order> visible = new HashSet<Order>();
for (AccessGroupName name: names) {
visible.addAll(visibilities.get(name));
}
return visible;
}
HashMap查找是O(1)。迭代ArrayList是O(n)。将项添加到HashSet是O(n)。总的来说,这将是O(n),其中n是添加列表中元素的总数(如果存在重叠,则可能大于结果集中元素的数量)。常量大致是从ArrayList迭代器中获取元素所花费的时间加上向HashSet添加内容所需的时间 - 前者大约为10个周期,后者接近100个。
除了AccessGroupName和Order实例本身之外,内存使用大约每组14-15个字加上每个订单1-2个字。主要是对象标题。
这段代码并没有做任何巧妙的事情,但我认为你很难以超过200个周期的常数击败O(n)。
特别是,如果名义矩阵是稀疏的(也就是说,如果有很多访问组,每个订单都有几个订单),这将使得裤子在一个bitset方法中击败,这将浪费大量的空间在零上,ORing上的时间归零。