Home > database >  Is there a way of optimizing Dijkstra algorithm other than using A*?
Is there a way of optimizing Dijkstra algorithm other than using A*?

Time:11-30

I need to find the shortest path between 2 points in a Graph

This task must be done in C language

I chose to use Dijkstra's algorithm to solve this problem. When working with 442 vertexes, I instantly find the path with no problems, however, when working with 6111 and 12605 (teacher's test cases), the algorithm begins to slow down so much at the point that it takes 8 minutes to find one single path.

My graph implementation works with adjacent lists to prevent n^2 size.

The Dijkstra that I implemented was based in ComputerPhile's video https://www.youtube.com/watch?v=GazC3A4OQTE, using priority queue, with a while(current_vertex != destination && get_size(priority_queue) > 0), also the priority of each node on the priority queue is calculated using street_length or street_length/average_speed.

Because of the vertexes are on a plane, I tried doing a A* adaptation adding to the cost of each node from the priority queue the Euclidian distance between the current vertex position, and the destination vertex.

The Code

EDIT: Optimized with one if

while(search != destination) {

        if(find_element(visited_vertexes, search, compare) == NULL) { //Added this if

            void* search_adjacents = list_of_adjacents_by_address(search);

            for(void* aux = get_head(search_adjacents); aux; aux = get_next(aux)){

                void* edge = get_list_element(aux);

                if(edge_get_from(edge) != edge_get_to(edge)) {

                    void* edge_data = edge_get_data(edge);
                    void* edge_to = edge_get_to(edge);

                    double cost_until_this_point = operation_mode(edge_data)   search_cost;
                    
                    void* found = find_element(visited_vertexes, edge_to, compare);

                    if(found == NULL && edge_to != back_track) {

                        priority_queue_insert(prior_queue, new_helper(edge_to, search, cost_until_this_point   distance_dijkstra(edge_to, destination)), cost_until_this_point   distance_dijkstra(edge_to, destination)); // Are we able to use a* ?

                    }

                }
                
            }

        }

        back_track = search; // Update to compare with the next vertex

        helper* top = priority_queue_pop(prior_queue, false, free_helper);

        insert_list(visited_vertexes, top); // Updated visited vertexes, remove from the priority queue

        helper* next_vertex = priority_queue_get_element(priority_queue_get_head(prior_queue));

        if(!next_vertex) break;

        search = next_vertex->vertex;
        search_cost = next_vertex->cost;
        
}

So far, I've done this. I think it's slow because of the priority of a lot of cases is very close. Is there any suggestion to optimize more this Dijkstra?

P.S:


typedef struct helper{

    void* vertex; //Current vertex
    void* from; //Where it came from
    double cost; //Cost until here

} helper;

void* new_helper(void* vertex, void* from, double cost) {

    helper* aux = calloc(1, sizeof(helper));
    aux->vertex = vertex;
    aux->from = from;
    aux->cost = cost;

    return aux;

}

CodePudding user response:

Problem solved with a if(find_element(visited_vertexes, search, compare) == NULL) before starting the analysis of the current vertex. This prevents that an already visited and analyzed vertex is inserted again, on the priority queue.

  • Related