国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判颍荒嫱負(fù)渑判?;關(guān)鍵路徑

這篇具有很好參考價值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判颍荒嫱負(fù)渑判?;關(guān)鍵路徑。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

1、最小生成樹

1.1 概念?

1.2 普利姆算法(Prim)

1.3 克魯斯卡爾算法(Kruskal)?

2、最短路徑

2.1 迪杰斯特拉算法(Dijkstra)

2.2 弗洛伊德算法(Floyd)?

2.3 BFS算法,Dijkstra算法,F(xiàn)loyd算法的對比

3、有向無環(huán)圖描述表達(dá)式

3.1 有向無環(huán)圖定義及特點

3.2 描述表達(dá)式

4、拓?fù)渑判?/p>

4.1 AOV網(wǎng)

4.2 步驟?

4.3 DFS實現(xiàn)拓?fù)渑判?

5、逆拓?fù)渑判?/p>

5.1 步驟?

5.2 DFS實現(xiàn)逆拓?fù)渑判??

6、關(guān)鍵路徑

6.1 AOE網(wǎng)?

6.2 求解方法

6.3 特性?


1、最小生成樹

1.1 概念?

????????最小生成樹是一種基于圖的算法,用于在一個連通加權(quán)無向圖中找到一棵生成樹,使得樹上所有邊的權(quán)重之和最小。最小生成樹指一張無向圖的生成樹中邊權(quán)最小的那棵樹。生成樹是指一張無向圖的一棵極小連通子圖,它包含了原圖的所有頂點,但只有足以構(gòu)成一棵樹的 n-1 條邊。最小生成樹可以用來解決最小通信代價、最小電纜費用、最小公路建設(shè)等問題。常見的求解最小生成樹的算法有Prim算法和Kruskal算法。

?【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判?;逆拓?fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

1.2 普利姆算法(Prim)

?????????Prim算法的基本思想是從一個任意頂點開始,每次添加一個距離該頂點最近的未訪問過的頂點和與之相連的邊,直到所有頂點都被訪問過。

其基本步驟如下:

  1. 初始化:定義一個空的集合S表示已經(jīng)確定為最小生成樹的結(jié)點集合,和一個數(shù)組dist表示當(dāng)前結(jié)點到S集合中最短距離,初始時S集合為空,數(shù)組dist中所有元素為正無窮,將任意一個結(jié)點u加到S集合中。

  2. 找到到S集合距離最近的結(jié)點v,并將v加入到S集合中。

  3. 更新數(shù)組dist,更新S集合中的結(jié)點到其它結(jié)點的距離。對于所有不在S集合中的結(jié)點w,如果從v到w的距離小于dist[w],則更新dist[w]的值為從v到w的距離。

  4. 重復(fù)以上步驟2和步驟3,直到所有的結(jié)點都加入到S集合中,即構(gòu)成了最小生成樹。

該算法的時間復(fù)雜度為O(n^2),其中n為圖的頂點數(shù)。

以下是用C語言實現(xiàn)Prim算法的代碼,假設(shè)圖的節(jié)點從0到n-1編號。

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

#define MAX_N 1000    // 最大頂點數(shù)
#define INF INT_MAX   // 正無窮
#define false 0
#define true 1

// 無向圖的鄰接矩陣表示法
int graph[MAX_N][MAX_N];   // 圖的鄰接矩陣
int visited[MAX_N];        // 標(biāo)記結(jié)點是否已加入最小生成樹
int dist[MAX_N];           // 記錄結(jié)點到最小生成樹的距離
int parent[MAX_N];         // 記錄結(jié)點的父節(jié)點(即最小生成樹的邊)

int prim(int n)
{
    // 初始化
    for (int i = 0; i < n; i++) {
        visited[i] = false;
        dist[i] = INF;
        parent[i] = -1;
    }
    dist[0] = 0;  // 從結(jié)點0開始構(gòu)建最小生成樹

    for (int i = 0; i < n - 1; i++) {  // n - 1次循環(huán)
        int min_dist = INF;
        int min_index = -1;
        // 找出距離最小生成樹最近的結(jié)點
        for (int j = 0; j < n; j++) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                min_index = j;
            }
        }
        if (min_index == -1) {
            break;  // 找不到未訪問的結(jié)點,算法結(jié)束
        }
        visited[min_index] = true;
        // 更新未加入最小生成樹的結(jié)點到最小生成樹的距離和父節(jié)點
        for (int j = 0; j < n; j++) {
            if (!visited[j] && graph[min_index][j] < dist[j]) {
                dist[j] = graph[min_index][j];
                parent[j] = min_index;
            }
        }
    }
    // 輸出最小生成樹
    int cost = 0;
    for (int i = 1; i < n; i++) {
        printf("%d -> %d : %d\n", parent[i], i, graph[i][parent[i]]);
        cost += graph[i][parent[i]];
    }
    return cost;
}

int main()
{
    int n;           // 結(jié)點數(shù)量
    int m;           // 邊數(shù)量
    scanf("%d%d", &n, &m);
    // 初始化鄰接矩陣
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            graph[i][j] = INF;
        }
    }
    // 讀入邊
    for (int i = 0; i < m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        graph[u][v] = w;
        graph[v][u] = w;  // 無向圖,所以要加上反向邊
    }
    int cost = prim(n);
    printf("cost = %d\n", cost);
    return 0;
}
 

????????dist數(shù)組記錄的是結(jié)點到最小生成樹的距離,parent數(shù)組記錄的是結(jié)點的父節(jié)點,visited數(shù)組記錄結(jié)點是否已加入最小生成樹。在每次循環(huán)中,找出距離最小生成樹最近的結(jié)點,并將其標(biāo)記為已訪問,再更新未加入最小生成樹的結(jié)點到最小生成樹的距離和父節(jié)點。最后輸出最小生成樹的邊,以及最小生成樹的總權(quán)值(即邊的權(quán)值之和)。

1.3 克魯斯卡爾算法(Kruskal)?

????????Kruskal算法的基本思想是先將圖中所有邊按邊權(quán)從小到大排序,然后逐個加入到生成樹中,但是要保證加入后生成樹仍然是無環(huán)的。如果加入某一條邊形成了環(huán),則不加入該邊,繼續(xù)考慮下一條邊。?

步驟如下:

  1. 將所有邊按照邊權(quán)從小到大排序;
  2. 初始化一個空的樹;
  3. 從排序后的邊列表中選擇權(quán)重最小的邊,并判斷這條邊的兩個端點是否在同一棵樹中;
  4. 如果這條邊的兩個端點不在同一棵樹中,則將這條邊加入最小生成樹中,并將這兩個端點所在的樹合并成一棵樹;
  5. 重復(fù)步驟3和步驟4,直到所有的邊都被考慮過。

?以下是用C語言實現(xiàn)Kruskal算法的代碼,假設(shè)圖的節(jié)點從0到n-1編號。

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

#define MAX_N 1000    // 最大頂點數(shù)
#define INF INT_MAX   // 正無窮
#define false 0
#define true 1

// 邊的結(jié)構(gòu)體
typedef struct Edge {
    int u;
    int v;
    int w;
} Edge;

Edge edges[MAX_N * MAX_N];  // 邊集合
int parent[MAX_N];         // 記錄結(jié)點的父節(jié)點
int rank[MAX_N];           // 記錄結(jié)點所在集合的秩

int cmp(const void* a, const void* b)
{
    Edge* edge1 = (Edge*)a;
    Edge* edge2 = (Edge*)b;
    return edge1->w - edge2->w;
}

int find(int x)
{
    // 路徑壓縮
    if (parent[x] != x) {
        parent[x] = find(parent[x]);
    }
    return parent[x];
}

void unite(int x, int y)
{
    // 按秩合并
    int root_x = find(x);
    int root_y = find(y);
    if (rank[root_x] < rank[root_y]) {
        parent[root_x] = root_y;
    } else {
        parent[root_y] = root_x;
        if (rank[root_x] == rank[root_y]) {
            rank[root_x]++;
        }
    }
}

int kruskal(int n, int m)
{
    // 初始化
    for (int i = 0; i < n; i++) {
        parent[i] = i;
        rank[i] = 0;
    }
    // 按邊權(quán)從小到大排序
    qsort(edges, m, sizeof(Edge), cmp);
    // 構(gòu)建最小生成樹
    int cost = 0;
    int count = 0;
    for (int i = 0; i < m; i++) {
        int u = edges[i].u;
        int v = edges[i].v;
        int w = edges[i].w;
        if (find(u) != find(v)) {    // 判斷是否在同一個集合中
            unite(u, v);
            cost += w;
            count++;
            if (count == n - 1) {    // 邊數(shù)等于n-1,生成樹構(gòu)建完成
                break;
            }
        }
    }
    // 輸出最小生成樹邊
    for (int i = 0; i < n; i++) {
        if (parent[i] == i) {   // 找到根節(jié)點
            for (int j = 0; j < m; j++) {
                if ((edges[j].u == i && parent[edges[j].v] == i)
                    || (edges[j].v == i && parent[edges[j].u] == i)) {
                    printf("%d -> %d : %d\n", edges[j].u, edges[j].v, edges[j].w);
                }
            }
        }
    }
    return cost;
}

int main()
{
    int n;           // 結(jié)點數(shù)量
    int m;           // 邊數(shù)量
    scanf("%d%d", &n, &m);
    // 讀入邊并構(gòu)建邊集合
    for (int i = 0; i < m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        edges[i].u = u;
        edges[i].v = v;
        edges[i].w = w;
    }
    int cost = kruskal(n, m);
    printf("cost = %d\n", cost);
    return 0;
}
 

????????其中,邊的結(jié)構(gòu)體包括起點、終點和邊權(quán)。在Kruskal算法中,先對邊按照權(quán)值從小到大進行排序,每次取出最小的邊,如果它不連通任何已經(jīng)選出的邊,則加入最小生成樹中。為了判斷兩個結(jié)點是否在同一個集合中,可以使用并查集的數(shù)據(jù)結(jié)構(gòu),其中parent數(shù)組記錄結(jié)點的父節(jié)點,rank數(shù)組記錄結(jié)點所在集合的秩。并查集的find和unite函數(shù)實現(xiàn)路徑壓縮和按秩合并。最后輸出最小生成樹的邊,以及最小生成樹的總權(quán)值(即邊的權(quán)值之和)。?

2、最短路徑

2.1 迪杰斯特拉算法(Dijkstra)

????????Dijkstra算法是一種解決單源最短路徑問題的貪心算法,它的基本思路是從起點開始,每次選擇當(dāng)前最短路徑中的一個頂點,然后更新它的鄰居的最短路徑。

以下是Dijkstra算法的詳細(xì)步驟:

  1. 初始化數(shù)據(jù)結(jié)構(gòu):創(chuàng)建一個距離數(shù)組dist,用來記錄起點到每個頂點的最短距離,初始化為正無窮;創(chuàng)建一個visited數(shù)組,記錄每個頂點是否被訪問過;創(chuàng)建一個前驅(qū)數(shù)組path,記錄每個頂點的前驅(qū)頂點。

  2. 將起點的dist設(shè)為0,將visited設(shè)為false,將path設(shè)為null。

  3. 對于起點的所有鄰居,更新它們的dist為起點到鄰居的距離,并將它們的path設(shè)為起點。

  4. 重復(fù)以下步驟,直到所有頂點都被訪問過: a. 從未被訪問過的頂點中,選擇dist最小的頂點作為當(dāng)前頂點。 b. 將當(dāng)前頂點設(shè)為已訪問。 c. 對當(dāng)前頂點的所有鄰居,如果當(dāng)前頂點到鄰居的距離比鄰居的dist值小,就更新鄰居的dist值和path值。

  5. 通過prev數(shù)組可找到從起點到任意頂點的最短路徑。

?下面是一個使用C語言實現(xiàn)Dijkstra算法的示例:

#include <stdio.h>
#include <limits.h>

#define V 6    // 頂點數(shù)

// 尋找dist數(shù)組中最小值對應(yīng)的下標(biāo)
int minDistance(int dist[], bool visited[])
{
    int min = INT_MAX, min_index;

    for (int v = 0; v < V; v++)
        if (visited[v] == false && dist[v] <= min)
            min = dist[v], min_index = v;

    return min_index;
}

// 打印最短路徑
void printPath(int path[], int dest)
{
    if (path[dest] == -1)
        return;

    printPath(path, path[dest]);
    printf("%d ", dest);
}

// 打印最短路徑和距離
void printSolution(int dist[], int path[], int src)
{
    printf("Vertex\tDistance\tPath");
    for (int i = 0; i < V; i++)
    {
        printf("\n%d -> %d\t%d\t\t%d ", src, i, dist[i], src);
        printPath(path, i);
    }
}

// Dijkstra算法
void dijkstra(int graph[V][V], int src)
{
    int dist[V];     // 存儲src到各個頂點的最短距離
    bool visited[V]; // 標(biāo)記頂點是否已訪問過
    int path[V];     // 存儲最短路徑

    // 初始化
    for (int i = 0; i < V; i++)
        dist[i] = INT_MAX, visited[i] = false, path[i] = -1;

    dist[src] = 0;

    // 計算最短路徑
    for (int count = 0; count < V - 1; count++)
    {
        int u = minDistance(dist, visited);

        visited[u] = true;

        for (int v = 0; v < V; v++)
            if (!visited[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v])
                dist[v] = dist[u] + graph[u][v], path[v] = u;
    }

    // 打印結(jié)果
    printSolution(dist, path, src);
}

int main()
{
    // 構(gòu)建鄰接矩陣
    int graph[V][V] = {
        {0, 4, 0, 0, 0, 0},
        {4, 0, 8, 0, 0, 0},
        {0, 8, 0, 7, 0, 4},
        {0, 0, 7, 0, 9, 14},
        {0, 0, 0, 9, 0, 10},
        {0, 0, 4, 14, 10, 0}
    };

    dijkstra(graph, 0);    // 計算從0開始的最短路徑

    return 0;
}
 

????????在上述代碼中,我們使用鄰接矩陣來表示圖,使用dist數(shù)組來記錄起點到各個頂點的最短距離,使用visited數(shù)組來記錄頂點是否已訪問過,使用path數(shù)組來記錄最短路徑。

2.2 弗洛伊德算法(Floyd)?

????????Floyd算法是一種動態(tài)規(guī)劃算法,用于解決有向圖中任意兩點之間的最短路徑問題。?時間復(fù)雜度為O(n^3),其中n為節(jié)點數(shù)。其步驟如下:

????????1. 創(chuàng)建一個n × n的矩陣D來表示任意兩點之間的最短距離,其中n為圖的頂點數(shù)。

????????2. 初始化矩陣D,對于每個頂點i,設(shè)其到自身的距離為0,對于所有i和j之間存在邊的情況,設(shè)其距離為對應(yīng)的邊權(quán)值,如果不存在邊,則將對應(yīng)的D[i][j]設(shè)為無窮大。

????????3. 對于任意的k∈[1,n],依次考慮頂點1~n,并計算經(jīng)過頂點k的最短路徑,即計算D[i][j] = min(D[i][j], D[i][k] + D[k][j]),其中i,j∈[1,n]。

????????4. 經(jīng)過第3步的計算后,矩陣D中存儲的即為任意兩點之間的最短距離。

????????5. 如果矩陣D中存在負(fù)環(huán),說明存在一些頂點之間的距離可以無限縮小,此時無法得到正確的最短路徑。

????????6. 如果需要求出最短路徑,則需要借助于一個前驅(qū)矩陣P,其中P[i][j]表示從i到j(luò)的最短路徑上,j的前驅(qū)頂點是哪個。可以通過在計算D[i][j]時,將P[i][j]設(shè)置為經(jīng)過的頂點k,來得到前驅(qū)矩陣P。

?下面是C語言實現(xiàn)Floyd算法的示例代碼:

#include <stdio.h>
#include <limits.h>

#define INF INT_MAX
#define MAXN 100

int dist[MAXN][MAXN];
int path[MAXN][MAXN];

void floyd(int n) {
    /* 初始化距離矩陣和路徑矩陣 */
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) {
                dist[i][j] = 0;
                path[i][j] = -1; /* 表示 i 到 j 沒有中間節(jié)點 */
            } else {
                dist[i][j] = INF;
                path[i][j] = -1;
            }
        }
    }

    /* 根據(jù)邊權(quán)值更新距離矩陣和路徑矩陣 */
    int u, v, w;
    while (scanf("%d %d %d", &u, &v, &w) == 3) {
        dist[u][v] = w;
        path[u][v] = u; /* i 到 j 的路徑經(jīng)過 u */
    }

    /* 計算任意兩點之間的最短路徑 */
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (dist[i][k] < INF && dist[k][j] < INF && dist[i][j] > dist[i][k] + dist[k][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                    path[i][j] = path[k][j]; /* i 到 j 的路徑經(jīng)過 u 的話,i 到 k 的路徑就經(jīng)過 u 了,于是將 i 到 k 的路徑經(jīng)過的節(jié)點掛到 i 到 j 的路徑上 */
                }
            }
        }
    }
}

void print_path(int u, int v) {
    if (path[u][v] == -1) { /* i 到 j 沒有中間節(jié)點 */
        printf("%d", v);
    } else { /* i 到 j 的路徑經(jīng)過 u */
        print_path(u, path[u][v]); /* 遞歸打印 i 到 u 的路徑 */
        printf("->%d", v);
    }
}

int main() {
    int n;
    scanf("%d", &n);

    floyd(n);

    int s, t;
    scanf("%d %d", &s, &t);

    printf("%d\n", dist[s][t]);
    print_path(s, t);

    return 0;
}
 

????????該代碼首先讀入圖的規(guī)模 n,然后讀入每條邊的起點、終點和邊權(quán)值,根據(jù)這些信息構(gòu)建鄰接矩陣。然后,它使用Floyd算法計算任意兩點之間的最短路徑和路徑矩陣。最后,給定起點 s?和終點 t,輸出它們之間的最短路程和路徑。

2.3 BFS算法,Dijkstra算法,F(xiàn)loyd算法的對比

?【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判?;逆拓?fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

3、有向無環(huán)圖描述表達(dá)式

3.1 有向無環(huán)圖定義及特點

????????有向無環(huán)圖(Directed Acyclic Graph,簡稱DAG)是一種有向圖,其中不存在環(huán)路,即從任意一個頂點出發(fā)不可能經(jīng)過若干條邊回到此頂點。通常用來表示任務(wù)調(diào)度、依賴關(guān)系等場景,具有以下特點:

1. 有向性:DAG中所有邊均有方向,即起點指向終點。

2. 無環(huán)性:DAG中不存在環(huán)路,即不能從一個頂點出發(fā)沿其周游返回此頂點。

3. 頂點與邊的關(guān)系:DAG中的頂點表示任務(wù)、事件、狀態(tài)等,邊表示依賴關(guān)系、控制關(guān)系等。

4. 拓?fù)渑判颍篋AG可以進行拓?fù)渑判?,即將DAG中所有頂點排序,使得對于任意一條邊(u,v),頂點u都排在v的前面。

3.2 描述表達(dá)式

?????????有向無環(huán)圖可以用于描述表達(dá)式的計算順序,其中每個節(jié)點表示一個操作符或操作數(shù),每個有向邊表示操作數(shù)或操作符之間的依賴關(guān)系和計算順序。

?【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判?;逆拓?fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

例如,對于表達(dá)式 "5*(2+3)":

????????首先,將 "+" 表示為一個節(jié)點,并有兩個入邊和一條出邊; 然后,將 "2" 和 "3" 也表示為節(jié)點,并分別與 "+" 節(jié)點相連; 接著,再將 "*" 表示為節(jié)點,并與 "5" 和 "+" 節(jié)點相連; 最后,整個有向無環(huán)圖如圖所示:

         +        // "+" 節(jié)點
        / \
       /   \
      2     3    // "2" 和 "3" 節(jié)點
       \   /
        \ /
         *       // "*" 節(jié)點
         |
         5       // "5" 節(jié)點

????????按照拓?fù)渑判虻捻樞虮闅v這個有向無環(huán)圖,就可以得到表達(dá)式的計算順序:2 -> 3 -> + -> 5 -> *,即先計算 2 和 3 的和,再將結(jié)果與 5 相乘,最后得到結(jié)果 25。

4、拓?fù)渑判?/h2>

4.1 AOV網(wǎng)

?【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判颍荒嫱負(fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

4.2 步驟?

拓?fù)渑判蚴菍τ邢驁D進行排序的一種算法,步驟如下:

1. 初始化:首先,將所有入度為0的頂點加入到一個隊列中。

2. 遍歷:從隊列中取出一個頂點,輸出該頂點并刪除該頂點的所有出邊(即將它所指向的頂點的入度減1)。如果該頂點刪除后所指向的結(jié)點入度為0,則將其加入隊列中。

3. 重復(fù)遍歷:重復(fù)以上操作,直到隊列為空為止。

4. 判斷:如果輸出的頂點數(shù)等于圖中的頂點數(shù),則拓?fù)渑判虺晒Γ⑤敵鼋Y(jié)果;否則,圖中存在環(huán),拓?fù)渑判蚴 ?/p>

?【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判?;逆拓?fù)渑判颍魂P(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

4.3 DFS實現(xiàn)拓?fù)渑判?

????????DFS實現(xiàn)拓?fù)渑判虻幕舅悸肥牵簭娜我庖粋€沒有后繼節(jié)點的節(jié)點出發(fā),沿著它的各個鏈路不斷深入,并記錄經(jīng)過的節(jié)點,直到到達(dá)一個沒有出邊的節(jié)點為止。在返回的過程中,將經(jīng)過的節(jié)點依次加入結(jié)果數(shù)組中,直到所有的節(jié)點都加入到結(jié)果數(shù)組中。

DFS實現(xiàn)拓?fù)渑判虻腃語言代碼示例:

#include <stdio.h>
#include <stdlib.h>
#define MAXN 1000

int n, m;
int G[MAXN][MAXN];  //鄰接矩陣存圖
int vis[MAXN], res[MAXN], idx = 0;  //vis數(shù)組用于記錄是否訪問過,res數(shù)組用于存儲結(jié)果

void dfs(int u){
    vis[u] = 1;  //標(biāo)記為已訪問
    for(int v = 0; v < n; v++){
        if(G[u][v] && !vis[v]){  //如果v是u的后繼節(jié)點且未被訪問過
            dfs(v);  //繼續(xù)深入
        }
    }
    res[idx++] = u;  //將該節(jié)點存入結(jié)果數(shù)組中
}

void topSort(){
    for(int i = 0; i < n; i++){
        if(!vis[i]){  //從未被訪問過的節(jié)點出發(fā)
            dfs(i);
        }
    }
    for(int i = n - 1; i >= 0; i--){  //倒序輸出結(jié)果數(shù)組
        printf("%d ", res[i]);
    }
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 0; i < m; i++){
        int u, v;
        scanf("%d%d", &u, &v);
        G[u][v] = 1;  //有向邊
    }
    topSort();
    return 0;
}
 

????????其中,G數(shù)組為鄰接矩陣存儲圖,vis數(shù)組用于記錄是否訪問過,res數(shù)組用于存儲結(jié)果,idx為結(jié)果數(shù)組的下標(biāo)。topSort函數(shù)是主要的拓?fù)渑判蛩惴?,遍歷所有節(jié)點并調(diào)用dfs函數(shù),dfs函數(shù)通過遞歸的方式實現(xiàn)深度優(yōu)先遍歷。最后,倒序輸出結(jié)果數(shù)組,即可得到拓?fù)渑判虻慕Y(jié)果。

5、逆拓?fù)渑判?/h2>

5.1 步驟?

????????逆拓?fù)渑判蚴侵冈谝粋€有向無環(huán)圖中,對于每個節(jié)點v,輸出所有能夠到達(dá)v的節(jié)點。逆拓?fù)渑判虻牟襟E如下:

1. 初始化一個空的結(jié)果列表和一個空的隊列。
2. 對于每個節(jié)點v,計算能夠到達(dá)v的節(jié)點數(shù)目,記為out_degree[v]。
3. 將所有out_degree[v]為0(出度為0)的節(jié)點加入隊列。
4. 當(dāng)隊列非空時,取出隊首節(jié)點u,并將其加入結(jié)果列表。
5. 對于u的每個鄰居節(jié)點v,將out_degree[v]減1。
6. 若out_degree[v]等于0,則將v加入隊列。
7. 重復(fù)步驟4-6直到隊列為空。
8. 返回結(jié)果列表。

【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判?;逆拓?fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

5.2 DFS實現(xiàn)逆拓?fù)渑判??

????????逆拓?fù)渑判蛑傅氖窃谝粋€有向無環(huán)圖(DAG)中,對所有節(jié)點進行排序,使得對于任意一條有向邊(u, v),都有排在前面的節(jié)點先于排在后面的節(jié)點。逆拓?fù)渑判蚩梢酝ㄟ^深度優(yōu)先搜索(DFS)實現(xiàn)。具體實現(xiàn)步驟如下:

  1. 定義一個數(shù)組visited,用于記錄每個節(jié)點是否已經(jīng)被訪問過,初始值為0。

  2. 定義一個棧stack,用于存儲已經(jīng)訪問過的節(jié)點。

  3. 對于每個節(jié)點u,進行DFS搜索,具體步驟如下:

    a. 標(biāo)記節(jié)點u已經(jīng)被訪問過,visited[u]=1。

    b. 對于節(jié)點u的每個鄰接節(jié)點v,如果該節(jié)點還沒有被訪問過,則進行DFS搜索。

    c. 將節(jié)點u入棧。

  4. 當(dāng)所有節(jié)點都搜索完畢后,從棧頂開始按順序取出節(jié)點,生成逆拓?fù)渑判蚪Y(jié)果。

下面是C語言實現(xiàn)代碼:

#include <stdio.h>
#define MAX_VERTEX_NUM 100

int visited[MAX_VERTEX_NUM], topo[MAX_VERTEX_NUM], top = -1;
int vex_num, arc_num;
int Graph[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

void DFS(int u) {
    visited[u] = 1;
    int v;
    for (v = 0; v < vex_num; v++) {
        if (Graph[u][v] == 1 && visited[v] == 0) {
            DFS(v);
        }
    }
    topo[++top] = u;
}

void TopoSort() {
    int i, j;
    for (i = 0; i < vex_num; i++) {
        visited[i] = 0;
    }
    top = -1;
    for (i = 0; i < vex_num; i++) {
        if (visited[i] == 0) {
            DFS(i);
        }
    }
    printf("逆拓?fù)渑判蚪Y(jié)果:");
    for (i = vex_num - 1; i >= 0; i--) {
        printf("%d ", topo[i]);
    }
}

int main() {
    int i, j, u, v;
    scanf("%d%d", &vex_num, &arc_num);
    for (i = 0; i < vex_num; i++) {
        for (j = 0; j < vex_num; j++) {
            Graph[i][j] = 0;
        }
    }
    for (i = 0; i < arc_num; i++) {
        scanf("%d%d", &u, &v);
        Graph[u][v] = 1;
    }
    TopoSort();
    return 0;
}

示例輸入:

7 10
0 1
0 2
1 3
1 5
1 4
2 5
3 6
4 6
5 4
5 6

示例輸出:

逆拓?fù)渑判蚪Y(jié)果:0 2 1 5 4 3 6

6、關(guān)鍵路徑

6.1 AOE網(wǎng)?

?【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判颍荒嫱負(fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

6.2 求解方法

????????關(guān)鍵路徑是某個項目中的最長路徑,它決定了整個項目的總時長,需要正確地計算和管理。以下是關(guān)鍵路徑的求解方法:

1. 確定項目的活動和它們的先后關(guān)系。

2. 繪制網(wǎng)絡(luò)圖,包括活動的節(jié)點和它們之間的連接線,確定每個活動的預(yù)計持續(xù)時間和最早開始時間。

3. 根據(jù)網(wǎng)絡(luò)圖計算每個活動的最早開始時間和最遲開始時間。

4. 計算每個活動的最早完成時間和最遲完成時間。

5. 通過計算每個活動的浮動時間,確定哪些活動是關(guān)鍵路徑上的活動。

6. 將關(guān)鍵路徑上的活動按照其完成時間的順序排列,找出整個項目的最長時間和關(guān)鍵路徑。

7. 對于非關(guān)鍵路徑上的活動,可以進行資源優(yōu)化,以縮短項目的總時長。

總之,關(guān)鍵路徑的求解需要清晰的項目規(guī)劃和正確的計算方法,能夠幫助項目管理人員更好地控制項目進度和資源,確保項目按時完成。

?【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判颍荒嫱負(fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

6.3 特性?

?【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判颍荒嫱負(fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=

博主正在學(xué)習(xí)中,如果博文中有解釋錯誤的內(nèi)容,請大家指出??

????????????圖的應(yīng)用的知識點總結(jié)就到這里啦,如果對博文還滿意的話,勞煩各位大佬兒動動“發(fā)財?shù)男∈帧绷粝履鷮Σ┪牡馁澓蛯Σ┲鞯年P(guān)注吧????????????

【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判?;逆拓?fù)渑判?;關(guān)鍵路徑,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),Dijkstra算法,Floyd算法,關(guān)鍵路徑,拓?fù)渑判? referrerpolicy=文章來源地址http://www.zghlxwxcb.cn/news/detail-731328.html

到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)】圖的應(yīng)用:最小生成樹;最短路徑;有向無環(huán)圖描述表達(dá)式;拓?fù)渑判?;逆拓?fù)渑判?;關(guān)鍵路徑的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)第11周 :(圖的遍歷及連通性 + 犯罪團伙 + 圖形窗口問題 + 最小生成樹的權(quán)值之和 + Jungle Roads )

    【問題描述】 根據(jù)輸入的圖的鄰接矩陣A,判斷此圖的連通分量的個數(shù)。請使用鄰接矩陣的存儲結(jié)構(gòu)創(chuàng)建圖的存儲,并采用BFS優(yōu)先遍歷算法實現(xiàn),否則不得分。 【輸入形式】 第一行為圖的結(jié)點個數(shù)n,之后的n行為鄰接矩陣的內(nèi)容,每行n個數(shù)表示。其中A[i][j]=1表示兩個結(jié)點鄰接

    2024年02月06日
    瀏覽(34)
  • 數(shù)據(jù)結(jié)構(gòu)——圖的最短路徑

    數(shù)據(jù)結(jié)構(gòu)——圖的最短路徑

    在圖中,求兩個不同頂點間的不同路徑中,邊的權(quán)值和最小的那條路徑。這條路徑就叫做 最短路徑(Shortest Path) ,第一個頂點叫做 源點(Source) ,最后一個頂點叫做 終點(Destination) 。 單源最短路徑問題: 從某固定源點出發(fā),求其到所有其他頂點的最短路徑。 ? ? ? ? 包

    2024年02月03日
    瀏覽(21)
  • 圖的最短路徑 (數(shù)據(jù)結(jié)構(gòu)實驗報告)

    圖的最短路徑 (數(shù)據(jù)結(jié)構(gòu)實驗報告)

    一、實驗?zāi)康?講清楚進行本實驗后要學(xué)到的知識、掌握的數(shù)據(jù)結(jié)構(gòu)及其定義和表示方法,講清楚所采用的算法。 掌握圖結(jié)構(gòu)的(鄰接矩陣)輸入方法 掌握圖結(jié)構(gòu)的說明、創(chuàng)建以及圖的存儲表示(鄰接矩陣) 掌握最短路徑算法原理 掌握最短路徑算法的編程實現(xiàn)方法 二、實驗

    2024年02月06日
    瀏覽(21)
  • 數(shù)據(jù)結(jié)構(gòu)與算法課程設(shè)計---最小生成樹的應(yīng)用

    數(shù)據(jù)結(jié)構(gòu)與算法課程設(shè)計---最小生成樹的應(yīng)用

    1.問題 假定有這么一個問題,有11個城市,城市之間有一些天然氣管道,鋪設(shè)天然氣管道需要花費不同的金額,現(xiàn)在要你選擇其中一些天然氣管道,使得所有城市可以互相聯(lián)通且花費最小。 2.分析 我們把這個問題抽象為一張圖,每個城市是一個頂點,城市與城市之間的管道是

    2024年02月08日
    瀏覽(26)
  • Java高階數(shù)據(jù)結(jié)構(gòu) & 圖的最短路徑問題

    Java高階數(shù)據(jù)結(jié)構(gòu) & 圖的最短路徑問題

    圖的最短路徑問題! 圖的基礎(chǔ)知識博客:傳送門 最短路徑問題: 從在帶權(quán)圖的某一頂點出發(fā),找出一條通往另一頂點的最短路徑, 最短也就是沿路徑各邊的權(quán)值總 和達(dá)到最小 。 一共會講解三種算法 Dijkstra算法【單源最短路徑】 Bellman-Ford算法【單源最短路徑】 改進:SPF

    2024年02月04日
    瀏覽(28)
  • 【Java高階數(shù)據(jù)結(jié)構(gòu)】圖的最短路徑問題

    【Java高階數(shù)據(jù)結(jié)構(gòu)】圖的最短路徑問題

    圖的最短路徑問題! 圖的基礎(chǔ)知識博客:傳送門 最短路徑問題: 從在帶權(quán)圖的某一頂點出發(fā),找出一條通往另一頂點的最短路徑, 最短也就是沿路徑各邊的權(quán)值總 和達(dá)到最小 。 一共會講解三種算法 Dijkstra算法【單源最短路徑】 Bellman-Ford算法【單源最短路徑】 改進:SPF

    2024年02月08日
    瀏覽(24)
  • C語言數(shù)據(jù)結(jié)構(gòu)——圖的最短路徑算法解決實例問題

    C語言數(shù)據(jù)結(jié)構(gòu)——圖的最短路徑算法解決實例問題

    一、問題描述 W公司在某個地區(qū)有6個產(chǎn)品銷售點,現(xiàn)根據(jù)業(yè)務(wù)需要打算在其中某個銷售點上建立一個中心倉庫,負(fù)責(zé)向其他銷售點提供產(chǎn)品。由于運輸線路不同,運輸費用也不同。假定每天需要向每個銷售點運輸一次產(chǎn)品,那么應(yīng)將中心倉庫建在哪個銷售點上,才能使運輸費

    2024年02月08日
    瀏覽(28)
  • 數(shù)據(jù)結(jié)構(gòu)(12)Dijkstra算法JAVA版:圖的最短路徑問題

    數(shù)據(jù)結(jié)構(gòu)(12)Dijkstra算法JAVA版:圖的最短路徑問題

    目錄 12.1.概述 12.1.1.無權(quán)圖的最短路徑 ?12.1.2.帶權(quán)圖的最短路徑 1.單源最短路徑 2.多源最短路徑 12.2.代碼實現(xiàn) 無權(quán)圖的最短路徑,即最少步數(shù),使用BFS+貪心算法來求解最短路徑,比較好實現(xiàn),此處不做展開討論。 有權(quán)圖的最短路徑,不考慮權(quán)重為負(fù)數(shù)的情況,因為權(quán)重為負(fù)

    2024年02月06日
    瀏覽(23)
  • 【數(shù)據(jù)結(jié)構(gòu)(30)】6.6 圖的應(yīng)用

    【數(shù)據(jù)結(jié)構(gòu)(30)】6.6 圖的應(yīng)用

    其中: 拓?fù)渑判?以及 關(guān)鍵路徑 針對的是一種特殊的圖,稱作 有向無環(huán)圖 。 生成樹 圖中所有頂點均由邊連接在一起,但是 不存在回路 的圖。 包含無向圖 G 所有頂點的 極小連通子圖 。 極小連通子圖 : 頂點的邊數(shù)目在這個連通子圖中的數(shù)目已經(jīng)達(dá)到最小。 如果在該圖中

    2024年02月01日
    瀏覽(20)
  • 數(shù)據(jù)結(jié)構(gòu):地圖著色問題——圖的應(yīng)用——回溯法

    數(shù)據(jù)結(jié)構(gòu):地圖著色問題——圖的應(yīng)用——回溯法

    目錄 前言 一、解決問題的思路 二、存儲結(jié)構(gòu)設(shè)計 三、代碼 1.創(chuàng)建圖函數(shù) 2.判斷色號是否相同函數(shù) 3.回溯函數(shù) 4.整體代碼 總結(jié) 本次解決的問題:用圖模擬部分地圖,對各省進行著色,要求相鄰省所使用的顏色不同,并保證使用的顏色總數(shù)最少。 先來一張效果圖 將鄰接矩陣

    2024年02月04日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包