C++无向带权图与最小生成树

C++无向带权图与最小生成树

参考《算法》一书,C++语言基于邻接表实现了无向带权图以及Prim算法得到图的最小生成树。图的实现在无向图的基础上增加权重即可,可参考《C++邻接表与图》。Prim算法简要说来,可写成如下伪代码:

for(int i=0;ii++)
{
  PrimVisit(i); //插入点并更新权重,同时得到更新后距离图最近的点
}

具体原理不再详述,可参考《算法》的讲解,此处记录C++实现无向带权图与最小生成树代码。

#include
#include
#include
#include
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<"-"<" "<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 << "("<weight<<")"<<" ";
            p = p->next;
        }
        cout << endl;
    }
}
int main()
{
    ALGraph* graph = new ALGraph();
    graph->CreateGraph();
    graph->PrintGraph();
    graph->Prim();
    return 0;
}

你可能感兴趣的:(Algorithm)