C++無向帶權圖與最小生成樹

C++無向帶權圖與最小生成樹

參考《算法》一書,C++語言基於鄰接表實現了無向帶權圖以及Prim算法得到圖的最小生成樹。圖的實現在無向圖的基礎上增加權重即可,可參考《C++鄰接表與圖》。Prim算法簡要說來,可寫成如下僞代碼:

for(int i=0;i<V;i++)
{
  PrimVisit(i); //插入點並更新權重,同時得到更新後距離圖最近的點
}

具體原理不再詳述,可參考《算法》的講解,此處記錄C++實現無向帶權圖與最小生成樹代碼。

#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;
/*
 頂點       中間節點
 VNode     ENode
 0 | A --> 2(C) 1(B)
 1 | B --> 4(E) 3(D) 0(A)
 2 | C --> 6(G) 5(F) 0(A)
 3 | D --> 7(H) 1(B)
 4 | E --> 7(H) 1(B)
 5 | F --> 6(G) 2(C)
 6 | G --> 5(F) 2(C)
 7 | H --> 4(E) 3(D)
 */
const int MAX = 20;
struct ENode      //鄰接表的中間節點
{
    int adjvex;    //對應索引
    double weight; //邊的權重
    ENode* next;
};
typedef struct VNode //鄰接表頂點
{
    int vertex;     //值
    ENode* firstarc; //指向第一個中間節點
}AdjList[MAX];
class ALGraph         //圖
{
private:
    AdjList adjList;          //鄰接表數組
    int vexNum;              //節點數量
    int arcNum;              //連邊數量
    bool visited[MAX];        //標記被訪問
    int edgeTo[MAX];          //最小生成樹連邊記錄
    double distTo[MAX];        //樹枝權重
public:
    void CreateGraph();       //創建圖
    void PrintGraph();        //打印圖
    void Prim();              //Prim算法尋找最小生成樹
    void PrimVisit(int& delmin);  //Prim算法插入結點並更新權值
};
void ALGraph::CreateGraph()
{
    cout << "請輸入圖的頂點數:" << endl;
    cin >> this->vexNum;
    cout << "請輸入圖的弧數:" << endl;
    cin >> this->arcNum;
    cout << "請輸入頂點信息:" << endl;
    for (int i = 0; i<this->vexNum; i++)  //構建頂點數組
    {
        cin >> this->adjList[i].vertex;
        this->adjList[i].firstarc = nullptr;
    }
    cout << "請輸入" << this->arcNum << "個弧的信息:" << endl;
    for (int i = 0; i<this->arcNum; i++)  //構建每條鄰接表
    {
        int h1, h2;
        double weight;
        cin >> h1 >> h2 >> weight;
        ENode* temp = new ENode();
        temp->adjvex = h2;
        temp->weight = weight;
        temp->next = this->adjList[h1].firstarc;
        this->adjList[h1].firstarc = temp;
        temp = new ENode();
        temp->adjvex = h1;
        temp->weight = weight;
        temp->next = this->adjList[h2].firstarc;
        this->adjList[h2].firstarc = temp;
    }
}
void ALGraph::Prim()
{
    int delmin=0;                  //記錄距離樹最近的圖節點,將其加入樹中
    for(int i=0;i<this->vexNum;i++)
    {
        visited[i] = false;
        distTo[i] = __DBL_MAX__;      //樹中權重初始化
    }
    for(int i=0;i<this->vexNum;i++)
    {
        PrimVisit(delmin);          //加入最近節點並更新權重
    }
    for(int i=0;i<this->vexNum;i++)   //打印生成樹
    {
        cout<<edgeTo[i]<<"-"<<i<<" "<<distTo[i]<<endl;
    }
}
void ALGraph::PrimVisit(int& delmin)
{
    double mindst = __DBL_MAX__;
    visited[delmin] = true;
    if(delmin==0)
    {
        edgeTo[0] = 0;
        distTo[0] = 0;
    }
    ENode* p = this->adjList[delmin].firstarc; //遍歷delmin所連節點,更新權重
    while(p)
    {
        if(visited[p->adjvex])
        {
            p = p->next;
            continue;
        }
        if(p->weight < distTo[p->adjvex])      //更新權重
        {
            edgeTo[p->adjvex] = delmin;
            distTo[p->adjvex] = p->weight;
        }
        p = p->next;
    }
    for(int i=0;i<this->vexNum;i++)           //找出下一個delmin
    {
        if(!visited[i] && mindst>distTo[i])
        {
            delmin = i;
            mindst = distTo[i];
        }
    }
}
void ALGraph::PrintGraph()
{
    for (int i = 0; i<this->vexNum; i++)
    {
        cout << this->adjList[i].vertex << "--------->";
        ENode* p = this->adjList[i].firstarc;
        while (p)
        {
            cout << this->adjList[p->adjvex].vertex << "("<<p->weight<<")"<<" ";
            p = p->next;
        }
        cout << endl;
    }
}
int main()
{
    ALGraph* graph = new ALGraph();
    graph->CreateGraph();
    graph->PrintGraph();
    graph->Prim();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章