Dijikstra和Bellman_ford算法

算法实现思路:

Dijkstra算法

预处理:将所有的节点除开始节点的访问位置为零表示没有找到大该节点的最短路径,用一个初始化为无穷大的距离数组存放到已经找到节点到未找到节点的距离的最小值,具体为:刚开始时候存放起始节点到其相邻节点的距离值,若节点不可达则记为无穷大,后续每次找到一个节点开始修改这个数组中的值,看看经过这个节点中转到达其余节点距离是不是更小,修改节点的时候顺便记录修改前的前驱节点,这样方便最后输出找到的路径。每一次找到节点就修改距离数组中的值,再找距离数组中的最小的值,将最小值对应的节点的访问为置为一表示找到该节点的最短路径,如此循环

bellmen_ford算法的实现思路:

第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。
第二,进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。

算法实现:

# include 

#define INFINITY 9999
#define MAX 10

typedef struct Edge {
    int s;
    int e;
    int v;
}Edge;

Bellman_ford算法实现:

void bellmen_ford(Edge edge[MAX], int vnum, int edgenum, int startnode)
{
    int dist[MAX];
    int pred[MAX];
    int i, j;
    // 第一步初始化
    for (int i = 0; i < vnum; i++)
    {

        dist[i] = INFINITY;
        pred[i] = startnode;
    }
    dist[startnode] = 0;

    for (int k = 0; k < vnum - 1; k++)//循环k-1次 
    {
        for (int i = 0; i < edgenum; i++)//循环每条边
        {
            if (dist[edge[i].e] > dist[edge[i].s] + edge[i].v)
            {//如果起点 s 的距离加上边的权值 v 小于终点 e 的距离,则更新终点 e 的距离值 d
                dist[edge[i].e] = dist[edge[i].s] + edge[i].v;
                pred[edge[i].e] = edge[i].s;//到e点经过s点 
            }
        }
    }

    for (int i = 0; i < vnum; i++)
        if (i != startnode)
        {
            if (dist[i] == INFINITY)
                printf("\n到达V[%d]节点的路径长度 = ∞", i);
            else
                printf("\n到达V[%d]节点的路径长度 = %d", i, dist[i]);

            if (dist[i] != INFINITY)
            {
                printf("\n路径 : V[%d]", i);
                j = i;
                do
                {
                    j = pred[j];
                    printf("  <<<<  V[%d]", j);
                } while (j != startnode);
            }
            else
            {
                printf("\n终点不可达");
            }
            printf("\n");
        }



}

Dijikstra算法实现:

void dijikstra(int G[MAX][MAX], int n, int startnode)
{
    int cost[MAX][MAX], distance[MAX], pred[MAX];
    int visited[MAX], count, mindistance, nextnode, i, j;
    //对邻接矩阵进行初步的处理,将0变成无穷大
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
            if (G[i][j] == 0)
                cost[i][j] = INFINITY;
            else
                cost[i][j] = G[i][j];

    //初始化距离数组
    for (i = 0; i < n; i++)
    {
        distance[i] = cost[startnode][i];
        pred[i] = startnode;
        visited[i] = 0;
    }
    distance[startnode] = 0;
    visited[startnode] = 1;
    count = 1;
    while (count < n - 1)
    {
        mindistance = INFINITY;
        for (i = 0; i < n; i++)//找到相邻的最小距离的哪个节点
            if (distance[i] < mindistance && !visited[i])
            {
                mindistance = distance[i];
                nextnode = i;
            }
        visited[nextnode] = 1;
        for (i = 0; i < n; i++)//修改存放最小距离的数组并修改前驱
            if (!visited[i])
                if (mindistance + cost[nextnode][i] < distance[i]) {
                    distance[i] = mindistance + cost[nextnode][i];
                    pred[i] = nextnode;
                }
        count++;
    }

    //输出路径
    for (i = 0; i < n; i++)
        if (i != startnode)
        {
            if (distance[i] == INFINITY)
                printf("\n到达V[%d]节点的路径长度 = ∞", i);
            else
                printf("\n到达V[%d]节点的路径长度 = %d", i, distance[i]);

            if (distance[i] != INFINITY)
            {
                printf("\n路径 : V[%d]", i);
                j = i;
                do
                {
                    j = pred[j];
                    printf("  <<<<  V[%d]", j);
                } while (j != startnode);
            }
            else
            {
                printf("\n终点不可达");
            }
            printf("\n");
        }

}

主函数:

int main()
{
    int vnum, edgenum, startnode;
    int G[MAX][MAX];
    int start, end, value;
    Edge edge[MAX];
    printf("输入图的 顶点数 和 边数:");
    scanf("%d %d", &vnum, &edgenum);

    for (int i = 0; i < vnum; i++)
        for (int j = 0; j < vnum; j++)
        {
            if (i == j)
                G[i][j] = 0;
            else
                G[i][j] = INFINITY;
        }

    printf("输入每条变的 起点 终点 以及其 权重:\n");
    for (int k = 0; k < edgenum; k++)
    {
        printf("(%d): ", k + 1);
        scanf("%d %d %d", &start, &end, &value);
        printf("\n");
        G[start][end] = value;
        edge[k].s = start;
        edge[k].e = end;
        edge[k].v = value;
    }
    printf("邻接矩阵是:\n");
    for (int i = 0; i < vnum; i++)
    {
        for (int j = 0; j < vnum; j++)
        {
            if (G[i][j] == INFINITY)
                printf("∞\t");
            else
                printf("%d\t", G[i][j]);
        }
        printf("\n");
    }
    printf("\n输入起始的顶点\t");
    scanf("%d", &startnode);
    printf("\n##################Dijikstra######################\n");
    dijikstra(G, vnum, startnode);

    printf("\n################Bellmen_Ford#####################\n");
    bellmen_ford(edge, vnum, edgenum, startnode);
    system("pause");
}

输入:

输入参数

输出邻接矩阵:

邻接矩阵

开始输入起始节点:

这里选择将零作为起始节点

输出结果:

输出结果

将所有代码拷到一个文件中就可以运行

你可能感兴趣的:(Dijikstra和Bellman_ford算法)