C++ 我的Prim算法(MST)在矩阵中的运行速度比在列表中快得多

C++ 我的Prim算法(MST)在矩阵中的运行速度比在列表中快得多,c++,algorithm,tree,C++,Algorithm,Tree,我在实现Prim算法寻找图中的最小生成树时遇到了一些问题。 1.我生成一个邻接矩阵,并运行算法来处理这个矩阵。守则: void Graph::Prim(){ int i=,j; int x=0,y=0,min,count=0; bool* visited=new bool[this->vertices_number]; // array of visited vertices for (int a=0;a<this->vertices_numb

我在实现Prim算法寻找图中的最小生成树时遇到了一些问题。 1.我生成一个邻接矩阵,并运行算法来处理这个矩阵。守则:

void Graph::Prim(){
    int i=,j;
    int x=0,y=0,min,count=0;
    bool* visited=new bool[this->vertices_number]; // array of visited vertices

    for (int a=0;a<this->vertices_number;a++)
        visited[a]=false;

    visited[0]=true; // checking the first vertex (start looking here)

    while(count < this->vertices_number-1){
    min=INFINITY; //defined in header (large int)
        for (int i=0;i<this->vertices_number;i++){              
            if (visited[i]==true){                              // looking for minimum-weight edge in all visited vertices
                for(j=0;j<this->vertices_number;j++){           //looking in one column
                    if (this->AdjacencyMatrix[i][j]<min && this->AdjacencyMatrix[i][j]>0 && visited[j]==false){ 
                    /* looking for lowest-weight edge which isn't already connected to the tree and isn't 0*/
                        min=AdjacencyMatrix[i][j]; //value
                        x=i;                        //row
                        y=j;                        //column
                    }
                }
            }
        }
        visited[y]=true; //  added vertex
    //  cout << x << "-->" << y << " : (" << min << ")"<<endl;
        count++; // visited vertex
    }
}
所以我创建了一个邻接列表:

list<Link> *AdjacencyList;
AdjacencyList=new list<Link>[vertices_number];
因此,最后将填充整个列表,例如,如果顶点0和4已连接且连接的权重为7,则AdjacencyList[0]包含目标为4且权重为7的链接

我只修改了算法的主循环,因此现在它使用迭代器查找所需内容:

    if (visited[i]==true){ 
        for(list<Link>::iterator it = AdjacencyList[i].begin(); it != AdjacencyList[i].end(); it++){
            if ( visited[it->destination]==false && it->weight < min){
                x=i;
                y=it->destination;
                min=it->weight;

这些算法能够毫无问题地找到相同的MST,唯一的问题是,在矩阵上工作的算法要快得多,这让我非常惊讶。例如,在一个80000边随机图中,当使用矩阵时,该树以毫秒为单位,但使用列表:整秒。有人能帮我一下吗,或者给我一个如何使代码更有效的提示吗?

我坚信使用数组的实现比使用列表的实现更快,因为它提供了更好的内存位置,也就是说,它对缓存更友好。

我坚信,使用阵列的实现比使用列表的实现更快,因为它提供了更好的内存位置,也就是说,它对缓存更友好。

原因是您正在进行非常密集的内存访问,因此,密集表示获胜。也就是说,在整个邻接矩阵上按行的主要顺序循环,这意味着充分利用了缓存。在链表的情况下,添加的每个新元素都在堆上分配了可能不连续的新内存


对于Prim,您应该使用某种形式的优先级队列。

这是因为您正在进行非常密集的内存访问,因此密集表示获胜。也就是说,在整个邻接矩阵上按行的主要顺序循环,这意味着充分利用了缓存。在链表的情况下,添加的每个新元素都在堆上分配了可能不连续的新内存


对于Prim,您应该使用某种形式的优先级队列。

您是否尝试过使用vector?是否尝试过预先为列表分配内存?向量具有保留函数。可能列表有这样的功能吗?@Prabhu:没有为列表预留空间这没有意义,但是如果你愿意使用虚拟元素,可以调整大小。我试过vector,它没有改变任何东西。你试过vector吗?试过为列表预先分配内存吗?向量具有保留函数。可能列表有这样的东西吗?@Prabhu:列表没有保留它没有意义,但是如果你愿意使用虚拟元素,它会调整大小。我尝试了vector,它没有改变任何东西。非常有可能,考虑到列表是一个非常专门的容器,它以内存效率换取稳定性,而vector和deque在许多情况下以稳定性为代价,内存效率要高得多。有趣的是,我认为,在使用矩阵时,在某个时候,我必须遍历每个索引,这将导致n^2复杂性。如果您想用数据更新答案,请使用相关基准测试:我尝试了向量而不是列表,但完成算法仍需要很长时间。如何使该程序在OE logV复杂度下运行?使用矩阵时的复杂度确实在^2,我刚刚检查了它,使用列表时的复杂度也是n^2,但时间增长得更快。根据这一点:我应该得到O E logV。非常可能,事实上,鉴于列表是一个非常专门的容器,它在稳定性方面权衡了内存效率,而vector和deque在许多情况下以稳定性为代价,内存效率要高得多。有趣的是,我认为,在使用矩阵时,在某个时刻,我将不得不遍历每个索引,这将导致n^2的复杂性。相关基准测试,以防您想用数据更新您的答案:我尝试了向量而不是列表,但完成算法仍然需要很长时间。如何使该程序在OE logV复杂度下运行?使用矩阵时的复杂度确实在^2,我刚刚检查了它,使用列表时的复杂度也是n^2,但时间增长得更快。根据这一点:我应该得到O E logV.OK,所以我应该有一个优先队列的边缘从每个顶点出来,在矩阵和列表表示中?然后,我不会在数据容器上循环,寻找最小的尚未链接的边缘,但我会将其保存在该队列中?是的,优先级队列的全部目的是通过某种优先级概念来跟踪项目。在这种情况下,您希望跟踪可以通过其边权重添加权重的潜在边。这意味着您不必每次都循环所有要添加的暂定边。好的,所以我应该有一个从每个顶点出来的边的优先级队列,在矩阵和列表r中
代表?然后,我不会在数据容器上循环,寻找最小的尚未链接的边缘,但我会将其保存在该队列中?是的,优先级队列的全部目的是通过某种优先级概念来跟踪项目。在这种情况下,您希望跟踪可以通过其边权重添加权重的潜在边。这意味着您不必每次都循环添加所有暂定边。
    if (visited[i]==true){ 
        for(list<Link>::iterator it = AdjacencyList[i].begin(); it != AdjacencyList[i].end(); it++){
            if ( visited[it->destination]==false && it->weight < min){
                x=i;
                y=it->destination;
                min=it->weight;