Dijkstra 算法中的节点没有被保存

Posted

技术标签:

【中文标题】Dijkstra 算法中的节点没有被保存【英文标题】:Nodes in Dijkstra's algorithm are not being saved 【发布时间】:2014-04-09 23:12:10 【问题描述】:

我在使用 Dijkstra 算法时遇到问题,因为我可以访问我创建的列表中的下一个节点,但我无法将信息保存到那个“下一个节点”。我使用的结构是在每个索引处保存节点的向量。我正在使用向量索引的地址来访问该索引处的节点。

我用这个例子中的节点制作了向量:Linked list with multiple parent and child nodes

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <limits>
#include <algorithm>
#include <queue>
#include <vector>
#define INFINITY 999

using namespace std;

struct node


int id;
int edge_weight;
int distance_to_source;
//used for reverse iteration to find the path
int previous;

//pointing to children of parent node and the addresses are stored
//in an array
struct node* next_node_list[3];
struct node* previous_node[3];

;



int Dijkstra(vector<node> sub,int source, int target)

//intializing for main while loops
int best_path_weight =0;
int end_of_loops= (sub.size());
int child = 0;

//intializing intial distances to INF to show that 
for(int i=0; i < end_of_loops; i++)


sub[i].distance_to_source = INFINITY;


//source is set to be 0
sub[source].distance_to_source=0;
//copy of sub for later access 
vector<node> copy = sub;

while(!sub.empty())

    cout << sub.size() << endl;

    if(sub[0].distance_to_source == INFINITY)
    
    cout << "new node distance2source is INF" << endl;
    break;

    
    for(int j = 0; (j < 1); j++)
    

        if((sub[source].next_node_list[j] == NULL))
        
        cout << "null child " <<endl;
        break;
        

        //nextnode = (sub[0]).next_node_list[j];

        child = (sub[0].distance_to_source) + ((sub[0].next_node_list[j]->edge_weight));


        if((child) < ((sub[0].next_node_list[j])->distance_to_source))
        

            //this is where my problem lies I beleive
            ((sub[0].next_node_list[j])->distance_to_source) = child;

            //used for a reference to have access to final paths
            copy[((sub[0].next_node_list[j])->id)].distance_to_source = child;

            ((sub[0].next_node_list[j])->previous) = sub[0].id;       
        


    best_path_weight = copy[target].distance_to_source;

    

    sub.erase(sub.begin());





return best_path_weight;




int main() 
vector<node> sub;

// changing size of graph
int number_of_vertices = 3;
int source = 0;
int target = 2;
if(target > number_of_vertices)
cout << "ERROR! target cannot be greater than the number of vertices!" << endl; 

for(int i=0; i < number_of_vertices; i++)

    //Push new node onto a vector 
    sub.push_back(node());
    //assigning information to nodes
    sub[i].id = i;
    sub[i].edge_weight = 2*i+1;

    for(int j = 0; j < 3; j++)
    
        sub[i].next_node_list[j]=NULL;
        sub[i].previous_node[j]=NULL;
    


//node linking declaration
//node 0
sub[0].next_node_list[0]=(&sub[1]);
sub[0].next_node_list[1]=(&sub[2]);

//node 1
sub[1].next_node_list[0]=(&sub[2]);
//sub[1].next_node_list[1]=(&sub[4]);
sub[1].previous_node[0]=(&sub[0]);

//node3
sub[2].previous_node[0]=(&sub[0]);
sub[2].previous_node[1]=(&sub[1]);

cout << "distance "<< Dijkstra(sub, source, target) << endl;


【问题讨论】:

【参考方案1】:

您正在存储指向向量中其他节点的指针。当您复制它时,新节点仍指向原始向量中的节点。特别是您在next_node_listprevious_node 中的指针。

如果您通过引用传递 sub,它可能开始工作。但是,将指针存储到动态容器中通常是不安全的。当从向量中添加和删除元素时,它们可以从内存中的原始位置移动。如果你从前面移除,那么所有剩余的元素都会向前移动。使用 push_back 时可能没有足够的空间,因此可能会进行新的分配并将元素复制/移动到全新的内存块中。

您可以尝试的一件事是使用std::vector&lt;std::shared_ptr&lt;node&gt;&gt;,而不是在next_node_listprevious_node 中使用原始节点指针,而是将它们设为std::weak_ptr&lt;node&gt;。这将允许您在保持连接完整性的同时对向量进行洗牌。

【讨论】:

我正在使用en.wikipedia.org/wiki/Dijkstra%27s_algorithm 的伪代码。你给我的建议对于向量的第一个索引是可以的,但在那之后我得到大于 4 的图形的错误答案。

以上是关于Dijkstra 算法中的节点没有被保存的主要内容,如果未能解决你的问题,请参考以下文章

最短路径算法(Dijkstra)

最短路径(Dijkstra算法)

最短路径 深入浅出Dijkstra算法(一)

最短路径算法:Dijkstra算法

最短路径算法:Dijkstra算法

POJ-1062 昂贵的聘礼---Dijkstra+枚举上界