1. 程式人生 > >最小生成樹與最短路徑樹程式碼

最小生成樹與最短路徑樹程式碼

最小生成樹演算法:PRIM和 KRUSKAL

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#define MAX_VERTEX_NUM 20
#define OK 1
#define ERROR 0
#define MAX 1000
using namespace std;
typedef struct Arcell
{
    double adj;
}Arcell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
    char
vexs[MAX_VERTEX_NUM]; //節點陣列 AdjMatrix arcs; //鄰接矩陣 int vexnum, arcnum; //圖的當前節點數和弧數 }MGraph; typedef struct Pnode //用於普利姆演算法 { char adjvex; //節點 double lowcost; //權值 }Pnode, Closedge[MAX_VERTEX_NUM]; //記錄頂點集U到V-U的代價最小的邊的輔助陣列定義 typedef struct Knode //用於演算法中儲存一條邊及其對應的2個節點 { char ch1; //節點1 char
ch2; //節點2 double value;//權值 }Knode, Dgevalue[MAX_VERTEX_NUM]; //----------------------------------------------------------------------------------- int CreateUDG(MGraph & G, Dgevalue & dgevalue); int LocateVex(MGraph G, char ch); int Minimum(MGraph G, Closedge closedge); void MiniSpanTree_PRIM(MGraph G, char
u); void Sortdge(Dgevalue & dgevalue, MGraph G); //----------------------------------------------------------------------------------- int CreateUDG(MGraph & G, Dgevalue & dgevalue) //構造無向加權圖的鄰接矩陣 { int i, j, k; cout << "請輸入圖中節點個數和邊/弧的條數:"; cin >> G.vexnum >> G.arcnum; cout << "請輸入節點:"; for (i = 0; i<G.vexnum; ++i) cin >> G.vexs[i]; for (i = 0; i<G.vexnum; ++i)//初始化陣列 { for (j = 0; j<G.vexnum; ++j) { G.arcs[i][j].adj = MAX; } } cout << "請輸入一條邊依附的定點及邊的權值:" << endl; for (k = 0; k<G.arcnum; ++k) { cin >> dgevalue[k].ch1 >> dgevalue[k].ch2 >> dgevalue[k].value; i = LocateVex(G, dgevalue[k].ch1); j = LocateVex(G, dgevalue[k].ch2); G.arcs[i][j].adj = dgevalue[k].value; G.arcs[j][i].adj = G.arcs[i][j].adj; } return OK; } int LocateVex(MGraph G, char ch) //確定節點ch在圖G.vexs中的位置 { int a; for (int i = 0; i<G.vexnum; i++) { if (G.vexs[i] == ch) a = i; } return a; } //typedef struct Pnode //用於普利姆演算法 //{ // char adjvex; //節點 // double lowcost; //權值 //}Pnode,Closedge[MAX_VERTEX_NUM]; //記錄頂點集U到V-U的代價最小的邊的輔助陣列定義 void MiniSpanTree_PRIM(MGraph G, char u)//普利姆演算法求最小生成樹 { int i, j, k; Closedge closedge; k = LocateVex(G, u); for (j = 0; j<G.vexnum; j++) { if (j != k) { closedge[j].adjvex = u; closedge[j].lowcost = G.arcs[k][j].adj; } } closedge[k].lowcost = 0; for (i = 1; i<G.vexnum; i++) { k = Minimum(G, closedge); cout << "(" << closedge[k].adjvex << "," << G.vexs[k] << "," << closedge[k].lowcost << ")" << endl; closedge[k].lowcost = 0; for (j = 0; j<G.vexnum; ++j) { if (G.arcs[k][j].adj < closedge[j].lowcost) { closedge[j].adjvex = G.vexs[k]; closedge[j].lowcost = G.arcs[k][j].adj; } } } } int Minimum(MGraph G, Closedge closedge) //求closedge中權值最小的邊,並返回其頂點在vexs中的位置 { int i, j; double k = 1000; for (i = 0; i<G.vexnum; i++) { if (closedge[i].lowcost != 0 && closedge[i].lowcost < k) { k = closedge[i].lowcost; j = i; } } return j; } int mini = 0;//樹最小代價 void MiniSpanTree_KRSL(MGraph G, Dgevalue & dgevalue)//克魯斯卡爾演算法求最小生成樹 { int p1, p2, i, j; int bj[MAX_VERTEX_NUM]; //標記陣列 for (i = 0; i<G.vexnum; i++) //標記陣列初始化 bj[i] = i; Sortdge(dgevalue, G);//將所有權值按從小到大排序 for (i = 0; i<G.arcnum; i++) { p1 = bj[LocateVex(G, dgevalue[i].ch1)]; p2 = bj[LocateVex(G, dgevalue[i].ch2)]; if (p1 != p2) { cout << "(" << dgevalue[i].ch1 << "," << dgevalue[i].ch2 << "," << dgevalue[i].value << ")" << endl; mini += dgevalue[i].value; for (j = 0; j<G.vexnum; j++) { if (bj[j] == p2) bj[j] = p1; } } } } void Sortdge(Dgevalue & dgevalue, MGraph G)//對dgevalue中各元素按權值按從小到大排序 { int i, j; double temp; char ch1, ch2; for (i = 0; i<G.arcnum; i++) { for (j = i; j<G.arcnum; j++) { if (dgevalue[i].value > dgevalue[j].value) { temp = dgevalue[i].value; dgevalue[i].value = dgevalue[j].value; dgevalue[j].value = temp; ch1 = dgevalue[i].ch1; dgevalue[i].ch1 = dgevalue[j].ch1; dgevalue[j].ch1 = ch1; ch2 = dgevalue[i].ch2; dgevalue[i].ch2 = dgevalue[j].ch2; dgevalue[j].ch2 = ch2; } } } } void main() { int i, j; MGraph G; char u; Dgevalue dgevalue; CreateUDG(G, dgevalue); cout << "圖的鄰接矩陣為:" << endl; for (i = 0; i<G.vexnum; i++) { for (j = 0; j<G.vexnum; j++) cout << G.arcs[i][j].adj << " "; cout << endl; } cout << "請輸入起始點:\n"; cin >> u; cout << "=============普利姆演算法===============\n"; cout << "構成最小代價生成樹的邊集為:\n"; MiniSpanTree_PRIM(G, u); cout << "============克魯斯科爾演算法=============\n"; cout << "構成最小代價生成樹的邊集為:\n"; MiniSpanTree_KRSL(G, dgevalue); printf("樹最小代價為:"); printf("%d\n",mini); }

樣例:

這裡寫圖片描述

這裡寫圖片描述

最短路徑樹演算法:Dijkstra

#include <iostream>
#include <climits>
using namespace std;

#define MAX_VERTEX_NUM 20  // 頂點數量上限 
typedef char VerType;      // 頂點結構 , 頂點的字母名稱 
typedef int ArcType;       // 邊的結構 , 權值 
typedef enum { DG, UDG } GKind;  // 圖型別,{有向圖,無向圖}

                                 // 圖的儲存結構 
typedef struct
{
    int verNum, arcNum;  // 頂點數量, 邊數量 
    GKind kind;          // 圖型別 
    VerType vertex[MAX_VERTEX_NUM];                 //頂點
    ArcType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];   //邊 
}Graph;


void CreateGraphByArray(Graph &G);                 // 建立圖G (通過預定義的陣列)
int  VertexLoc(const Graph &G, const VerType &v);  // 獲取頂點v在圖G中的位置 
void ShortestPath_Dijkstra(Graph &G, int k);       // 最短路徑演算法 (迪傑斯特拉演算法)


int main()
{
    Graph G;
    CreateGraphByArray(G);
    ShortestPath_Dijkstra(G, 0);
    return 0;
}


void CreateGraphByArray(Graph &G)
{
    G.kind = DG;

    const int vn = 5;
    VerType V[vn + 1] = { "12345" };

    const int en = 7;
    VerType V1[en + 1] = { "1122345" };  //表示點1到2的距離為2;1到5的距離為10···
    VerType V2[en + 1] = { "2535456" };
    ArcType E[en] = { 2,10,3,7,4,5,6};


    // 輸入頂點 
    G.verNum = vn;
    for (int i = 0; i < G.verNum; ++i) {
        G.vertex[i] = V[i];
    }

    // 初始化鄰接矩陣 
    for (int vi = 0; vi < G.verNum; ++vi) {
        for (int vj = 0; vj < G.verNum; ++vj) {
            G.arcs[vi][vj] = INT_MAX;
        }
    }

    // 輸入邊 
    G.arcNum = en;
    for (int i = 0; i < G.arcNum; ++i) {
        VerType &v1 = V1[i], &v2 = V2[i];
        ArcType &e = E[i];
        int vi = VertexLoc(G, v1), vj = VertexLoc(G, v2);
        if (vi == G.verNum || vj == G.verNum) {
            continue;
        }
        if (UDG == G.kind) {
            G.arcs[vi][vj] = G.arcs[vj][vi] = e;
        }
        else {
            G.arcs[vi][vj] = e;
        }
    }
}

int VertexLoc(const Graph &G, const VerType &v)
{
    for (int i = 0; i < G.verNum; ++i) {
        if (G.vertex[i] == v) {
            return i;
        }
    }
    return G.verNum;
}

void ShortestPath_Dijkstra(Graph &G, int v0)
{
    const int N = 5;    //此處設定頂點個數********************************
    bool S[N];          // 表示v0到vi的最短路徑是否已經確定 
    int Path[N];        // 表示v0到vi的最短路徑上的直接前驅頂點 
    long long D[N];     // 表示v0到vi的最短路徑長度 

    for (int v = 0; v < N; ++v) {
        S[v] = false;
        D[v] = G.arcs[v0][v];
        Path[v] = D[v] != INT_MAX ? v0 : -1;
    }
    S[v0] = true;
    D[v0] = 0;

    for (int i = 1; i < N; ++i) {
        int min = INT_MAX, v;
        for (int w = 0; w < N; ++w) {
            if (!S[w] && D[w] < min) {
                v = w;
                min = D[w];
            }
        }

        if (min != INT_MAX) {
            S[v] = true;
            for (int w = 0; w < N; ++w) {
                if (!S[w] && (D[v] + G.arcs[v][w] < D[w])) {
                    D[w] = D[v] + G.arcs[v][w];
                    Path[w] = v;
                }
            }
        }
    }

    /* 輸出最短路徑 */
    for (int vi = 0; vi < N; ++vi) {
        cout << "最短路徑:";

        cout << G.vertex[vi];
        if (S[vi]) {


            for (int vj = Path[vi]; vj != -1; vj = Path[vj]) {
                cout << "←" << G.vertex[vj];
            }


            cout << "   距離為:" << D[vi]  << endl;
        }
        else {
            cout << " (INF)" << endl;
        }
    }
}

結果:

這裡寫圖片描述

相關推薦

小生成樹路徑程式碼

最小生成樹演算法:PRIM和 KRUSKAL #include<stdio.h> #include<stdlib.h> #include<iostream> #define MAX_VERTEX_NUM 20 #defi

小生成樹路徑--C語言實現

的區別 find 延遲 遍歷 最短路徑 標記 += 創建 png 接昨天,在這裏給出圖的其中一種應用:最小生成樹算法(Prime算法和Kruskal算法)。兩種算法的區別就是:Prime算法以頂點為主線,適合用於頂點少,邊密集的圖結構;Kruskal算法以邊為主線,適合於頂

小生成樹路徑的區別以及實現方法

一 區別最小生成樹能夠保證整個拓撲圖的所有路徑之和最小,但不能保證任意兩點之間是最短路徑。最短路徑是從一點出發,到達目的地的路徑最小。二 實現方法1. 最小生成樹最小生成樹有兩種演算法來得到:Prims演算法和Kruskal演算法。Kruskal演算法:根據邊的加權值以遞增

圖的小生成樹 VS 路徑

圖的應用問題 note 僅作入門參考的記錄 1. 網路架設之路徑最短問題 參考給出了兩個演算法:Prim 演算法和Kruskal演算法,前者針對鄰接矩陣,後者針對邊集陣列。

小生成樹路徑的總結

1.求最小生成樹有兩種方法: ①克魯斯卡爾演算法:這個演算法是以邊為單位(包括邊的所有的資訊:兩個端點+權值)進行儲存的,然後將邊按照權值的從小到大的順序進行排序,然後將第一條邊連線起來,第二條邊連線起來,就這樣一直迴圈,直到所有的邊都被連線起來為止,在這期間,你需要判斷

圖(Graph)——小生成樹路徑、Kruskal、Dijkstra、Floyd

4. 最小生成樹 4.1 生成樹 (1)定義:所有頂點均由邊連線在一起,但不存在迴路的圖叫該圖的生成樹 (2)深度優先生成樹與廣度優先生成樹 (3)     一個圖可以有許多棵不同的生成樹    所有

資料結構:圖——圖的遍歷、小生成樹路徑演算法

前言 在這裡,如果大家對圖或者資料結構還不太熟悉,想找一個動態的生成過程來參考,這是一個不錯的網站. 知識框架 圖的定義 線上性結構中,資料元素之間滿足唯一的線性關係,每個資料元素(除第一個和最後一個外)只有一個直接前趨和一個直接後繼; 在樹形結構中,資料元素之間有著明顯的層次關係,

圖的遍歷、小生成樹路徑

這一篇我們要總結的是圖(Graph),圖可能比我們之前學習的線性結構和樹形結構都要複雜,不過沒有關係,我們一點一點地來總結,那麼關於圖我想從以下幾點進行總結: 1,圖的定義? 2,圖相關的概念和術語? 3,圖的建立和遍歷? 4,最小生成樹和最短路徑? 5,演算法實現? 回到頂部一,圖的定義 什麼

[學習-思考-探究]莫隊算法 曼哈頓小生成樹分塊區間詢問算法

所有 我們 轉移 關鍵字 這樣的 不必要 時間復雜度 大於 莫隊算法 前段時間刷了一些莫隊算法的題目,這裏記錄了一些理解和思考。莫隊算法算法莫隊算法用於解決一類可以由區間[l,r]的答案可以快速轉移出區間[l-1,r],[l+1,r],[l,r+1],[l,r-1]的區間離

[學習-思考-探究]莫隊算法 曼哈頓小生成樹分塊區間詢問算法-2

iostream using space style 聯系 const ear math 模版 若要轉載,不需要聯系我,只需要在下面回復一下並註明原文。 在線區間詢問算法(增強算法) 考慮保存狀態 例題:小Z的襪子 如果對小Z的襪子應用基礎算法,會發生什麽? 小Z的襪子這道

[學習-思考-探究]莫隊算法 曼哈頓小生成樹分塊區間詢問算法-3

tdi push_back col none ast 查找 循環 pac 生成 若要轉載,不需要聯系我,只需要在下面回復一下並註明原文。 在線區間詢問算法(增強算法)2 #include <iostream> #include <algorithm>

bzoj 2561: 小生成樹小割】

inf front ostream ring pos clu clas 要求 || 看錯題了以為多組詢問嚇得不行…… 其實還挺好想的,就是數據範圍一點都不網絡流。把U作為s,V作為t,以最小生成樹為例,(U,V,L)要在最小生成樹上,就要求所有邊權比L小的邊不能連通(U,V

POJ-2485 Highways---小生成樹大邊

style ble include void ack return 最小生成樹 color spa 題目鏈接: https://vjudge.net/problem/POJ-2485 題目大意: 求最小生成樹中的最大邊 思路: 是稠密圖,用prim更好,但是規模不大,kru

PKUACM 2018 D Chocolate 小生成樹 Kruskal 長公共子序列

size and this put first test case ren The was $ \rightarrow $ 戳我進POJ原題 D:Chocolate 總時間限制: 1000ms $ \quad $ 內存限制: 65536kB   描述 Vincent is

BZOJ 2561 小生成樹小割)

任重而道遠  給定一個邊帶正權的連通無向圖G=(V,E),其中N=|V|,M=|E|,N個點從1到N依次編號,給定三個正整數u,v,和L (u≠v),假設現在加入一條邊權為L的邊(u,v),那麼需要刪掉最少多少條邊,才能夠使得這條邊既可能出現在最小生成樹上,也可能出現在最大生成樹上? Inp

POJ 2485 - Highways(求小生成樹大權值-Kruskal演算法)

題目 Language:Default Highways Time Limit: 1000MS

小生成樹大比率 UVALive - 5713

題目連結:https://vjudge.net/problem/UVALive-5713 題意:給出t組資料,每組資料第一行給出一個n,表示點的數量,接下來n行,每行有三個數字,分別是點的座標x,y和點的值w。現在我們要用n-1條邊來連線這n個點,秦始皇希望這n-1條邊的權值之和最小,現在徐福說他可以讓其中

小生成樹之kruskal演算法(附程式碼

prim演算法是通過找距離最近的節點來擴充最小生成樹的,稠密圖選擇prim演算法效率比較高,但是對於稀疏圖呢,prim演算法就顯的比較雞肋了。對於稀疏圖,有一個叫做kruskal的演算法。此演算法求稀疏圖的效率比較高,時間複雜度為O(ElogE)。 kruskal演算法主要

BZOJ 2177: 曼哈頓小生成樹 曼哈頓小生成樹

2177: 曼哈頓最小生成樹 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 281  Solved: 117 [Submit][Status][Discuss] Description 平面座標系xOy內,給定n個頂點