在图中找到所有可能的路线时无法摆脱死胡同

时间:2015-12-08 21:11:16

标签: c graph

所以我做了一个关于在图中查找用户指定的两个节点之间的所有路径的功课。代码有效但有一个小问题。

要了解我正在谈论的内容,请查看图表连接的外观: Beautifully drawn graph

(我知道我应该是艺术家而不是计算机工程师。)

所以我告诉程序告诉我节点0和3之间的所有可能路由。这是输出(不是精确输出):

0-3

0-1-2-3

0-2-1-3

问题在于最后一条路线。而不是0-2-3,它是0-2-1-3。因为它不知道1是死路一条。所以要么我不应该为死胡同节点做任何事情,要么在我明白它们已经死路一条时不打印它们。

我尝试做一些递归的东西来检查下一个节点是否是一个死胡同,但结果却是无限循环。

那么我该如何解决这个问题?

/*
   Description: Finds all possible routes from a starting node to an end node
                that is picked by the user.

   NOTE: This code is working in devc++ but it has problems in visual studio
          because of different functions.

*/

#include <stdio.h>
#include <string.h>

find_routes2(int start, int finish, char route[9], char route_temp[9],
             int mark[4], int graph[4][4])
{
    int i;
    char route_temp2[9];

    for(i = 0; i < 4; i++) {
        if (graph[start][i] != 0 && mark[i] != 0) {
            sprintf(route_temp2, "-> %d", i);
            strcat(route, route_temp2);
            if (i == finish) {
                printf("\nRoute: %s\n", route);
                strcpy(route, route_temp);
            } else {
                mark[start] = 0;
                find_routes2(i, finish, route, route_temp, mark, graph);
            }
        }
    }
}

find_routes(int start, int finish, char route[9], char route_temp[9],
            int mark[4], int graph[4][4])
{
    int i;
    char route_temp2[9];

    for (i = 0; i < 4; i++) {
        if (graph[start][i] != 0 && mark[i] != 0) {
            sprintf(route_temp2, "-> %d ", i);
            strcat(route, route_temp2);

            if (i == finish) {
                printf("\nRoute: %s\n\n", route);
            } else {
                mark[start] = 0;
                find_routes2(i, finish, route, route_temp, mark, graph);
            }
            memset(mark, 1, 4*sizeof(int));
            strcpy(route, route_temp);
        }
    }
}

int main()
{
    int graph[4][4] = { { 0, 1, 1, 1 }, { 1, 0, 1, 0 },
                        { 1, 1, 0, 1 }, { 1, 0, 1, 0 } };
    int mark[4] = { 1, 1, 1, 1 };
    char route[9];
    char route_temp[9];
    int i, j;

    printf("NOTE: This code is working in devc++ but it has problems \n"
           "in visual studio because of different functions\n\n");
    printf("This is the graph(nodes are 0, 1, 2 ,3):\n\n0-1-2-3\n\n");
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            printf("%d ", graph[i][j]);
        }
        printf("\n\n");
    }

    printf("Select a starting node from \"0, 1, 2 ,3\": ");
    scanf("%d", &i);

    sprintf(route, "-> %d", i);

    strcpy(route_temp, route);

    printf("\nSelect a different ending node from \"0, 1, 2 ,3\""
           "(if you dont get any results it\n"
           "means either you entered wrong numbers or there are no routes): ");
    scanf("%d", &j);
    if (i == j || i > 3 || j >3 || i < 0 || j < 0) {
        printf("\nStart and finish nodes are same or wrong number(s) have"
               " been entered. Please try \nagain.\n");
        exit(1);
    }
    find_routes(i, j, route, route_temp, mark, graph);
    system("pause");
}

2 个答案:

答案 0 :(得分:1)

试试这个:

#include <stdio.h>
#include <stdlib.h>

void display_route (int route[4], int n)
{
    int i;

    for (i = 0; i < n; i++) {
        if (i > 0) {
            printf (", ");
        }
    printf ("%d", route[i]);
    }
    printf ("\n");
}

void find_routes_helper (const int graph[4][4], int finish,
                         int route[4], int n, int mark[4])
{
    // I is the last vertex of ROUTE
    int i = route[n - 1];
    int j;

    // if ROUTE ends at FINISH, the search is over
    if (i == finish) {
        display_route (route, n);
        return;
    }

    // for each vertex J adjacent to I that is not already in ROUTE
    for (j = 0; j < 4; j++) {
        if (!mark[j] && graph[i][j]) {
            // add J to ROUTE
            route[n] = j;
            n++;
            mark[j] = 1;
            // search routes that begin with ROUTE
            find_routes_helper (graph, finish, route, n, mark);
            // backtrack : remove J from ROUTE
            n--;
            mark[j] = 0;
        }
    }
}

void find_routes (const int graph[4][4], int start, int finish)
{
    int i;
    int route[4];
    int n;
    int mark[4];

    // set things up so that ROUTE consists exactly of START
    route[0] = start;
    n = 1;
    for (i = 0; i < 4; i++) {
        mark[i] = 0;
    }
    mark[start] = 1;

    find_routes_helper (graph, finish, route, n, mark);
}

int main ()
{
    int graph[4][4] = {
        { 0, 1, 1, 1 },
        { 1, 0, 1, 0 },
        { 1, 1, 0, 1 },
        { 1, 0, 1, 0 }
    };
    int i, j;

    printf("This is the graph (nodes are 0, 1, 2 ,3):\n\n0-1-2-3\n\n");
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            printf("%d ", graph[i][j]);
        }
        printf("\n");
    }
    printf ("\n");

    printf("Select a starting node from \"0, 1, 2 ,3\": ");
    scanf("%d", &i);

    printf("\nSelect a different ending node from \"0, 1, 2 ,3\" (if"
           " you don't get any results it means either you entered"
           " wrong numbers or there are no routes): ");
    scanf("%d", &j);
    if (i == j || i > 3 || j > 3 || i < 0 || j < 0) {
        printf("\nStart and finish nodes are same or wrong number(s) "
               " have been entered. Please try again.\n");
        exit(1);
    }

    find_routes (graph, i, j);
    return 0;
}

请注意搜索代码如何将路径表示为节点数组以及显示逻辑如何完全分离。另请注意辅助数据结构如何在find_routes()中声明并从main()隐藏。

答案 1 :(得分:0)

您可以在函数find_routes()中在递归堆栈的顶部打印发现的路径,但是如果您这样做,那么您可以在该函数的每次迭代中只打印一条路径 - 这是,每个选择的初始边缘只有一条路线。可以有不止一个这样的,例如从节点1到节点0的两个路由都以0开始 - > 2。

此外,您没有为函数find_routes2()提供任何机制来向其调用者指示它失败,因此您将为每个可能的初始段选择打印一条路径。

后者实际上是不太严重的问题;通过修复第一个将使它变得没有实际意义。为此,请在每次到达目标顶点时打印完整的已发现路径,而不是仅在您一直返回到递归顶部后才打印。

另请注意,您需要小心顶点标记。当您访问它们时,请注意标记您的节点,但是当您完成该访问并且准备好从您当前所在的任何节点尝试替代路由时,您无法 un 标记它们。这将阻止您发现某些图形中某些顶点对之间的所有可能路径,包括程序内置的顶点。