我们正在使用DELPHI XE7开发通用图库。目标图形大小是该图中约1个MIO顶点节点和~10个MIO边缘。我们进步的当前状态是TGraph类的基本实现和一些基本的图算法!
问题在于将数据插入到顶点和边缘列表的速度已经实现为TObjectList。我只能在这里提供一些碎片代码,但它可能有助于获得我的问题的相关要点
TGraph<Tdata> = Class
private
/// <summary>
/// TVertexList<Tdata>;
/// </summary>
_vertices: TObjectList<TVertex<Tdata>>;
/// <summary>
/// TEdgesList<TData>;
/// </summary>
_edges: TObjectList<TEdge<Tdata>>;
.....
end;
function TGraph<Tdata>.addVertex(u: TVertex<Tdata>): Integer;
var
u_index: Integer;
begin
if (not _vertices.Contains(u)) then
begin
u_index := _vertices.Count;
u.vertex_index := u_index;
Result := _vertices.Add(u);
end;
end;
procedure TGraph<Tdata>.addEdge(e: TEdge<Tdata>;
checkDuplicates: Boolean = true);
var
i, j: Integer;
begin
if (checkDuplicates) then
if (self._edges.Contains(e)) then exit;
/// normal add egde stuff
....
end;
如代码所示,我们使用TList包含的函数来检查图中是否已存在某些元素。速度分析表明,该算法的复杂度为n2,这对我们来说是致命的。
问题现在就像那样
a)是Delphi中list.contains(...)性能的速度真的是n²吗?
b)检查元素是否存在的任何更好的函数?
c)我们可以更改为其他任何更多的通用对象列表 更快的数据类型用于构建通用图形?
d)我知道C ++ Boost 或METIS / HMETIS Graph库,但我不能写短文 这些lib的时间框架评估程序。他们也受苦吗? N²构建大型图表的问题?
此图显示 checkDuplicates = false 为绿色曲线, checkDuplicates = true 条件为addegde的红色曲线...)。
答案 0 :(得分:2)
TObjectList<T>.Contains()
是否真的是O(n 2 )?
不,是O(n)。 Contains()
的实现只是一个线性搜索。您显示的图表不是线性的,但我们不知道您是如何生成它的。大概你的代码不会纯粹测试Contains()
的性能。
我的猜测是你在衡量你的名单的人口。对于你的代码将是O(n 2 )。简而言之,添加项目是O(n),并且由于您选择了容器,检查它们是否在列表中也是O(n),即您必须对每个添加到列表的行进行线性搜索。所以把它放在一起,你就有了O(n 2 )的表现。
检查元素是否存在的任何更好的函数?
如果您的数据保存在此类容器中,则不会。 TObjectList<T>
是性能方面的随机访问数组。如果您想要比O(n)
搜索性能更好,则需要选择其他容器。例如,TDictionary<K,V>
会为您提供O(1)
搜索效果。
我们可以更改为用于构建通用图表的任何其他更快的数据类型而不是
TObjectList<T>
吗?
见上文。
我知道C ++ Boost或METIS / HMETIS Graph库,但是我不能在这些lib的短时间范围内编写评估程序。在构建大型图表时,他们是否也遇到O(n 2 )问题?
我不知道。正如我所说,我们不知道你的图表来自哪里,所以我们实际上无法确定你在测量什么。但是,在添加新的库之前,该领域中任何体面的库肯定不会对所有边缘执行完全线性搜索。