求单源的最短路径

//用邻接表的方法存储网
#include<iostream>
#include<vector>
#include<string>
#include<malloc.h>
#define INF 0x3f3f3f
#define Node_MAX 20
using namespace std;

vector<int> PATH[Node_MAX];//存储路径
int D[Node_MAX];//存储路径长度
int P[Node_MAX];//存储过程中的路径长度

typedef struct ArcNode{
    int adjvex;//指向的另外顶点位置
    struct ArcNode *next;
    int length;
}ArcNode;
typedef struct VNode{
    char name;
    ArcNode *first;
}VNode;
typedef struct{
    VNode vexs[Node_MAX];//存储顶点
    int vexnum,arcnum;//图的顶点个数,弧的个数
    int kind;//图的类型,0代表无向图,1代表有向图
}LGraph;

int FindV(char v,VNode *p,int num)
{
    for(int t=0;t<num;t++)
        if(v==p[t].name) return t;
    cout<<"ERROR:输入空的顶点,结束"<<endl;
    exit(-1);
}
bool CreateDN(LGraph &G)
{
    cout<<"请输入有向图的顶点个数和弧的数量"<<endl;
    cin>>G.vexnum>>G.arcnum;
    cout<<"请依次输入顶点的名称"<<endl;
    for(int t=0;t<G.vexnum;t++)
    {
        cin>>G.vexs[t].name;
        G.vexs[t].first=NULL;
    }
    ArcNode *a=(ArcNode *)malloc(sizeof(ArcNode)*G.arcnum);//弧结点分配空间
    ArcNode **p=(ArcNode **)malloc(sizeof(ArcNode *)*G.vexnum);//*(p+t)指向过程中t顶点指向的最后弧结点
    for(int t=0;t<G.arcnum;t++)
    {
        char v1,v2;
        int i,j,x;
        cout<<"请输入第"<<t+1<<"条弧的弧尾弧头名称及长度"<<endl;
        cin>>v1>>v2>>x;
        i=FindV(v1,G.vexs,G.vexnum);
        j=FindV(v2,G.vexs,G.vexnum);
        (a+t)->adjvex=j;(a+t)->length=x;(a+t)->next=NULL;//创建弧结点
        if(G.vexs[i].first==NULL)
            *(p+i)=G.vexs[i].first=a+t;
        else
        {
            *(p+i)=(*(p+i))->next=a+t;
        }
    }
    return true;
}
bool CreateUDN(LGraph &G)
{
    cout<<"请输入无向图的顶点个数和弧的数量"<<endl;
    cin>>G.vexnum>>G.arcnum;
    cout<<"请依次输入顶点的名称"<<endl;
    for(int t=0;t<G.vexnum;t++)
    {
        cin>>G.vexs[t].name;
        G.vexs[t].first=NULL;
    }
    ArcNode *a=(ArcNode *)malloc(sizeof(ArcNode)*G.arcnum*2);//弧结点分配空间
    ArcNode **p=(ArcNode **)malloc(sizeof(ArcNode *)*G.vexnum);//*(p+t)指向过程中t顶点指向的最后弧结点
    for(int t=0;t<G.arcnum;t++)
    {
        char v1,v2;
        int i,j,x;
        cout<<"请输入第"<<t+1<<"条弧两端名称及长度"<<endl;
        cin>>v1>>v2>>x;
        i=FindV(v1,G.vexs,G.vexnum);
        j=FindV(v2,G.vexs,G.vexnum);
        (a+t)->adjvex=j;(a+t)->length=x;(a+t)->next=NULL;//创建弧结点
        (a+t+G.arcnum)->adjvex=i;(a+t+G.arcnum)->length=x;(a+t+G.arcnum)->next=NULL;//创建弧结点
        if(G.vexs[i].first==NULL)
            *(p+i)=G.vexs[i].first=a+t;
        else
        {
            *(p+i)=(*(p+i))->next=a+t;
        }
        if(G.vexs[j].first==NULL)
            *(p+j)=G.vexs[j].first=a+t;
        else
        {
            *(p+j)=(*(p+j))->next=a+t;
        }

    }
    return true;
}
bool CreateLGraph(LGraph &G)
{
    cout<<"请输入图的类型:有向图DN,无向图UDN"<<endl;
    string temp;
    cin>>temp;
    if(!temp.compare("DN")) G.kind=1;
    if(!temp.compare("UDN")) G.kind=0;
    switch(G.kind)
    {
    case 0:CreateUDN(G);
               break;
    case 1:CreateDN(G);
        break;
    default:
        cout<<"ERROR"<<endl;
        exit(-1);
    }
    return true;
}

void DIJ(LGraph &G,char v)//算G图各顶点到v的最短路径
{
    int w=FindV(v,G.vexs,G.vexnum);
    for(int t=0;t<G.vexnum;t++)
    {
        PATH[t].push_back(w);
        P[t]=INF;
        D[t]=INF;
    }
    D[w]=0;
    ArcNode *p=G.vexs[w].first;
    while(p!=NULL)
    {
        P[p->adjvex]=p->length;
        p=p->next;
    }
    for(int t=0;t<G.vexnum-1;t++) //需要进行G.vexnum-1次
    {
        int min=INF,e;

        for(int i=0;i<G.vexnum;i++)
        {
            if(min>=P[i] && D[i]==INF){min=P[i];e=i;}
        }
        D[e]=min;
        PATH[e].push_back(e);
        p=G.vexs[e].first;
        while(p!=NULL)
        {
            if(min+p->length < P[p->adjvex] && D[p->adjvex]==INF)
            {P[p->adjvex]=min+p->length;PATH[p->adjvex]=PATH[e];}
            p=p->next;
        }
    }
}
int main()
{
    char v;
    LGraph G;
    CreateLGraph(G);
/*  ArcNode *p;
    for(int t=0;t<G.vexnum;t++)
    {
        cout<<G.vexs[t].name<<endl;
        p=G.vexs[t].first;
        while(p!=NULL)
        {
            cout<<G.vexs[p->adjvex].name<<" ";
            p=p->next;
        }
        cout<<endl;
    }
*/

    cout<<"请输入单源最短路径的源顶点名称"<<endl;
    cin>>v;
    DIJ(G,v);
    for(int t=0;t<G.vexnum;t++)
    {
        cout<<v<<"->"<<G.vexs[t].name<<endl;
        for(vector<int>::iterator it=PATH[t].begin();it!=PATH[t].end();it++)
            cout<<G.vexs[*it].name<<" ";
        if(D[t]!=INF) cout<<endl<<D[t]<<endl;
        else cout<<endl<<"无" <<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值