站内搜索

有向图转换&遍历&拓扑&最短路径

原帖及讨论:http://bbs.bccn.net/thread-130955-1-1.html

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MaxStr 20
typedef int Status;
typedef int ElemType;
typedef struct{    
    ElemType VNode;
    int indgree;
    }VexType;
typedef struct Arc{
    VexType Adj;
    unsigned int Weight;
    struct Arc *NextArc;
    }ArcType;
typedef struct{                                    
    VexType *Vex;
    ArcType **FirstArc;                  //邻接表;
//    ArcType **InvertArc;               //逆邻接表;
    int VexNums;                         //顶点总数;
    }DLGraph;                            //图的邻接表结构定义;
typedef struct{
    ElemType *Vex;
    unsigned int **Arc;                                
    int VexNums;
    }DMGraph;                            //图的邻接矩阵结构定义;
//========================================================================================
Status CreateDMGraph(DMGraph *DMG);            //创建图的邻接矩阵;
Status DMG_Traver(DMGraph DMG);                //邻接矩阵的遍历;
Status DMG_DFS(DMGraph DMG,int v,int *Visited);      //邻接矩阵深度遍历(递  归);
Status DMG_DFS_Uni(DMGraph DMG,int v,int *Visited);  //邻接矩阵深度遍历(非递归);
Status DMG_BFS(DMGraph DMG,int v,int *Visited);      //邻接矩阵广度遍历;
Status DMG2DLG(DMGraph DMG,DLGraph *DLG);      //邻接矩阵转换为邻接表;
Status DLG_Traver(DLGraph DLG);                //邻 接 表的遍历;
Status DLG_DFS(DLGraph DLG,int v,int *Visited);      //邻 接 表深度遍历(递  归);
Status DLG_DFS_Uni(DLGraph DLG,int v,int *Visited);  //邻 接 表深度遍历(非递归);
Status DLG_BFS(DLGraph DLG,int v,int *Visited);      //邻 接 表广度遍历;
//---------------------------------------------------------
Status Topsort(DLGraph DLG,ElemType **ts);        //邻接表有向图的Topsort;
Status Dijkstra(DMGraph DMG,ElemType v,unsigned int *dist);//Dijkstra;
Status PRN_DK(DMGraph DMG,unsigned int ***dis);        //输出Dijkstra算法;
Status Floyd(DMGraph DMG,unsigned int ***flyd);        //Floyd;
Status PRN_DMGraph(DMGraph DMG);            //输出邻接矩阵;
Status PRN_DLGraph(DLGraph DLG);            //输出邻接表;
//========================================================================================
int main(void)
{
    int i,j;
    DMGraph DMG;    
    DLGraph DLG;
    ElemType *ts;
    unsigned int **dist,**flyd;
    printf(    " 一、创立有向图的邻接矩阵:/n");    
        CreateDMGraph(&DMG);
        PRN_DMGraph(DMG);
    printf("/n/n 二、有向图-邻接矩阵的遍历:/n");
        DMG_Traver(DMG);
    printf("/n/n 三、邻接矩阵转换为邻接表:/n");
        DMG2DLG(DMG,&DLG);    
        PRN_DLGraph(DLG);
    printf("/n/n 四、有向图-邻接表的遍历:/n");
        DLG_Traver(DLG);
    printf("/n/n 五、邻接表有向图的拓扑排序:/n");
        Topsort(DLG,&ts);
    printf("/n/n/n");system("pause");
    printf("/n/n 六、邻接矩阵有向图的各点最短路径:/n/n  1. Dijkstra(迪杰斯特拉算法):");
        PRN_DK(DMG,&dist);
    printf("/n/n/n  2. Floyd(弗洛伊德算法):");
        Floyd(DMG,&flyd);

    printf("/n");    system("pause");
    printf("/n/n/nDijkstra最短路径测试输出:/n 某两点 : 最短路径");
    for(i = 1;i <= DMG.VexNums;i++)
        for(j = 1;j <= DMG.VexNums;j++)
            if(dist[i][j] < INT_MAX) printf("/n[%2d,%2d] : %5d ",i,j,dist[i][j]);
    printf("/n/nFloyd最短路径测试输出:/n 某两点 : 最短路径");
    for(i = 1;i <= DMG.VexNums;i++)
        for(j = 1;j <= DMG.VexNums;j++)
            if(flyd[i][j] < INT_MAX) printf("/n[%2d,%2d] : %5d ",i,j,flyd[i][j]);
    printf("/n");    system("pause");
    return 0;
}

//    文件格式参见"无向图"说明:
//http://bbs.bc-cn.net/dispbbs.asp?boardID=179&ID=129767

Status CreateDMGraph(DMGraph *DMG)        //创建图的邻接矩阵;
{
    char ReadFileName[MaxStr];
    unsigned int w;
    FILE *fp;
    int i,j;
    do{
        printf("/n     输入文本文件名:");
        gets(ReadFileName);
    }while(ReadFileName[0] == '/0' || !(fp = fopen(ReadFileName,"r")));

    fscanf(fp,"%d",&DMG->VexNums);        //得到顶点总数;
    if(!(DMG->Vex = (ElemType *)malloc((DMG->VexNums+1)*sizeof(ElemType))))
        {printf("/n内存溢出。");return 1;}
    if(!(DMG->Arc = (unsigned int **)malloc((DMG->VexNums+1)*sizeof(unsigned int*))))
        {printf("/n内存溢出。");return 1;}
    for(i = 1;i <= DMG->VexNums;i++)    //邻接矩阵初始化;
    {
        DMG->Vex[i] = i;        //
        if(!(DMG->Arc[i]=(unsigned int *)malloc((DMG->VexNums+1)*sizeof(unsigned int))))
            {printf("/n内存溢出。");return 1;}
        for(j = 1;j <= DMG->VexNums;j++)
        {
            DMG->Arc[i][j] = INT_MAX;
        }
    }
    while(fscanf(fp,"%d%d%u",&i,&j,&w) == 3)    DMG->Arc[i][j] = w;//
    fclose(fp);
    return 0;
}
//========================================================================================
Status DMG2DLG(DMGraph DMG,DLGraph *DLG)    //图的邻接矩阵转换为邻接表;
{
    int i,j;
    ArcType *p = NULL;
    DLG->VexNums = DMG.VexNums;
    if(!(DLG->Vex = (VexType *)malloc((DLG->VexNums+1)*sizeof(VexType))))
        {printf("/n内存溢出。");return 1;}
    if(!(DLG->FirstArc = (ArcType **)malloc((DLG->VexNums+1)*sizeof(ArcType*))))
        {printf("/n内存溢出。");return 1;}
    for(i = 1;i <= DLG->VexNums;i++)
    {
        DLG->Vex[i].VNode = DMG.Vex[i];    //
        DLG->FirstArc[i] = NULL;
        DLG->Vex[i].indgree = 0;
        for(j = 1;j <= DMG.VexNums;j++)
        {
            if(DMG.Arc[i][j] < INT_MAX)
            {
                if(!(p = (ArcType *)malloc(sizeof(ArcType))))
                    {printf("/n内存溢出。");return 1;}
                p->Adj.VNode = DMG.Vex[j];
                p->Weight = DMG.Arc[i][j];
                p->NextArc = DLG->FirstArc[i];
                DLG->FirstArc[i] = p;
            }
        }
        for(j = 1;j <= DMG.VexNums;j++)
        {
            if(DMG.Arc[j][i] < INT_MAX)    ++DLG->Vex[i].indgree;
        }
    }
    return 0;
}
//========================================================================================
Status DMG_Traver(DMGraph DMG)    //邻接矩阵的遍历;
{
    int i,*Visited;
    if(!(Visited = (int *)malloc((DMG.VexNums+1)*sizeof(int))))
        {printf("/n内存溢出。");return 1;}    
    printf("/n  1. 图的深度遍历:/n递  归:");    
    for(i = 1;i <= DMG.VexNums;i++)        Visited[i] = 0;    
    for(i = 1;i <= DMG.VexNums;i++)        
        if(Visited[i] == 0)        DMG_DFS(DMG,i,Visited);
    printf("/n非递归:");
    for(i = 1;i <= DMG.VexNums;i++)        Visited[i] = 0;
    for(i = 1;i <= DMG.VexNums;i++)
        if(Visited[i] == 0)        DMG_DFS_Uni(DMG,i,Visited);
    printf("/n/n  2. 图的广度遍历:/n/t");    
    for(i = 1;i <= DMG.VexNums;i++)        Visited[i] = 0;
    for(i = 1;i <= DMG.VexNums;i++)
        if(Visited[i] == 0)        DMG_BFS(DMG,i,Visited);
    return 0;
}
//========================================================================================
Status DLG_Traver(DLGraph DLG)    //邻 接 表的遍历;
{
    int i,*Visited;
    if(!(Visited = (int *)malloc((DLG.VexNums+1)*sizeof(int))))
        {printf("/n内存溢出。");return 1;}    
    printf("/n  1. 图的深度遍历:/n递  归:");    
    for(i = 1;i <= DLG.VexNums;i++)        Visited[i] = 0;
    for(i = 1;i <= DLG.VexNums;i++)
        if(Visited[i] == 0)        DLG_DFS(DLG,i,Visited);
    printf("/n非递归:");
    for(i = 1;i <= DLG.VexNums;i++)        Visited[i] = 0;
    for(i = 1;i <= DLG.VexNums;i++)
        if(Visited[i] == 0)        DLG_DFS_Uni(DLG,i,Visited);
    printf("/n/n  2. 图的广度遍历:/n/t");    
    for(i = 1;i <= DLG.VexNums;i++)        Visited[i] = 0;
    for(i = 1;i <= DLG.VexNums;i++)
        if(Visited[i] == 0)        DLG_BFS(DLG,i,Visited);
    printf("/n");
    return 0;
}
//========================================================================================
Status DMG_DFS(DMGraph DMG,int v,int *Visited)    //邻接矩阵深度遍历(递  归);
{
    int i;
    Visited[v] = 1;
    printf("%2d ->",v);
    for(i = 1;i <= DMG.VexNums;i++)
        if(Visited[i] == 0 && DMG.Arc[v][i] < INT_MAX)
            DMG_DFS(DMG,i,Visited);
    return 0;
}
//========================================================================================
Status DLG_DFS(DLGraph DLG,int v,int *Visited)    //邻 接 表深度遍历(递  归);
{
    ArcType *p = NULL;
    Visited[v] = 1;
    printf("%2d ->",v);
    p = DLG.FirstArc[v];
    while(p != NULL)
    {
        if(Visited[p->Adj.VNode] == 0)    DLG_DFS(DLG,p->Adj.VNode,Visited);
        p = p->NextArc;
    }
    return 0;
}
//========================================================================================
Status DMG_DFS_Uni(DMGraph DMG,int v,int *Visited)    //邻接矩阵深度遍历(非递归);
{
    int i,*Stack,top = -1;
    if(!(Stack = (int *)malloc((DMG.VexNums+1)*sizeof(int))))
        {printf("/n内存溢出。");return 1;}
    Visited[v] = 1;
    printf("%2d ->",v);
    Stack[++top] = v;
    while(top != -1)
    {
        for(i = 1;i <= DMG.VexNums;i++)
            if(Visited[i] == 0 && DMG.Arc[Stack[top]][i] < INT_MAX)
            {
                Visited[i] = 1;
                printf("%2d ->",i);
                Stack[++top] = i;
                break;
            }
        if(i == DMG.VexNums+1)    --top;
    }
    return 0;
}
//========================================================================================
Status DLG_DFS_Uni(DLGraph DLG,int v,int *Visited)    //邻 接 表深度遍历(非递归);
{
    int *Stack,top = -1;
    ArcType *p = NULL;
    if(!(Stack = (int *)malloc((DLG.VexNums+1)*sizeof(int))))
        {printf("/n内存溢出。");return 1;}
    Visited[v] = 1;
    printf("%2d ->",v);
    Stack[++top] = v;
    while(top != -1)
    {
        p = DLG.FirstArc[Stack[top]];
        while(p != NULL)
        {
            if(Visited[p->Adj.VNode] == 0)
            {
            Visited[p->Adj.VNode] = 1;
            printf("%2d ->",p->Adj.VNode);
            Stack[++top] = p->Adj.VNode;
            break;
            }
            p = p->NextArc;
        }
        if(p == NULL)    --top;
    }
    return 0;
}
//========================================================================================
Status DMG_BFS(DMGraph DMG,int v,int *Visited)    //邻接矩阵广度遍历;
{
    int i,*Queue,rear,front;
    if(!(Queue = (int *)malloc((DMG.VexNums+1)*sizeof(int))))
        {printf("/n内存溢出。");return 1;}
    Visited[v] = 1;
    printf("%2d ->",v);
    rear = front = 0;
    rear = (rear+1)%DMG.VexNums;
    Queue[rear] = v;
    while(rear != front)
    {
        front = (front+1)%DMG.VexNums;
        for(i = 1;i <= DMG.VexNums;i++)
            if(Visited[i] == 0 && DMG.Arc[Queue[front]][i] < INT_MAX)
            {
                Visited[i] = 1;
                printf("%2d ->",i);
                rear = (rear+1)%DMG.VexNums;
                Queue[rear] = i;
            }
    }
    return 0;
}
//========================================================================================
Status DLG_BFS(DLGraph DLG,int v,int *Visited)    //邻 接 表广度遍历;
{
    ArcType *p = NULL;
    int *Queue,rear,front;
    if(!(Queue = (int *)malloc((DLG.VexNums+1)*sizeof(int))))
        {printf("/n内存溢出。");return 1;}
    rear = front = 0;
    Visited[v] = 1;
    printf("%2d ->",v);
    rear = (rear+1)%DLG.VexNums;
    Queue[rear] = v;
    while(rear != front)
    {
        front = (front+1)%DLG.VexNums;
        p = DLG.FirstArc[Queue[front]];
        while(p != NULL)
        {
            if(Visited[p->Adj.VNode] == 0)
            {
                Visited[p->Adj.VNode] = 1;
                printf("%2d ->",p->Adj);
                rear = (rear+1)%DLG.VexNums;
                Queue[rear] = p->Adj.VNode;
            }
            p = p->NextArc;
        }
    }
    return 0;
}
//========================================================================================
Status Topsort(DLGraph DLG,ElemType **ts)    //邻接表有向图的Topsort拓扑排序;
{
    int i,j,k,m = 0,top = -1;
    ArcType *tp,*p;
    if(!(*ts = (ElemType *)malloc((DLG.VexNums+1)*sizeof(ElemType))))
        {printf("/n内存溢出。");return 1;}
    if(!(tp = (ArcType *)malloc((DLG.VexNums+1)*sizeof(ArcType))))
        {printf("/n内存溢出。");return 1;}
    printf("   Topsort:/n/n   ");
    for(i = 1;i <= DLG.VexNums;i++)            //初始化tp;
    {
        tp[i].Adj.VNode = DLG.Vex[i].VNode;
        tp[i].NextArc = DLG.FirstArc[i];
        tp[i].Adj.indgree = DLG.Vex[i].indgree;
        if(DLG.Vex[i].indgree == 0)
        {
            tp[i].Adj.indgree = top;
            top = i;
        }
    }
    while(top != -1)
    {
        j = top;
        top = tp[top].Adj.indgree;
        printf(" %2d ,",tp[j].Adj.VNode);
        ++m;
        p = tp[j].NextArc;
        while(p != NULL)
        {
            k = p->Adj.VNode;
            --tp[k].Adj.indgree;
            if(tp[k].Adj.indgree == 0)
            {
                tp[k].Adj.indgree = top;
                top = k;
            }
            p = p->NextArc;
        }
    }
    if(m < DLG.VexNums)    printf("/n不能拓扑!/n");
    return 0;
}
//========================================================================================
Status PRN_DK(DMGraph DMG,unsigned int ***dis)        //输出Dijkstra最短路径;
{
    int i,j,flag;
    unsigned int **dist;
    if(!(dist = (unsigned int **)malloc((DMG.VexNums+1)*sizeof(unsigned int*))))
        {printf("/n内存溢出。");return 1;}
    *dis = dist;
    for(i = 1;i <= DMG.VexNums;i++)
    {
        if(!(dist[i] = (unsigned int *)malloc((DMG.VexNums+1)*sizeof(unsigned int))))
            {printf("/n内存溢出。");return 1;}
        Dijkstra(DMG,i,dist[i]);    //Dijkstra最短路径;
    }
    for(i = 1;i <= DMG.VexNums;i++)
    {
        flag = 0;
        printf("/n从%3d出发的最短路径:",i);
        for(j = 1;j <= DMG.VexNums;j++)
        {
            if(j != i && dist[i][j] < INT_MAX)
            {
                printf("/n/t自%3d ==>%3d点:%4d",i,j,dist[i][j]);
                flag = 1;
//if(j != i && dist[i][j] == INT_MAX)        printf("/n/t自%3d ==>%3d点:  ∞",i,j);
//else if(j == i);printf("/n/t自%3d ==>%3d点:%4d",i,j,dist[i][j]);
            }
        }
        if(flag == 0)    printf("/n/t没有任何路径...555555");    
    }
    return 0;
}
//========================================================================================
Status Dijkstra(DMGraph DMG,ElemType v,unsigned int *dist)//最短路径Dijkstra(迪杰斯特拉);
{
    int i,j,t;
    ElemType *flag;
    unsigned int min;    
    if(!(flag = (ElemType *)malloc((DMG.VexNums+1)*sizeof(ElemType))))
        {printf("/n内存溢出。");return 1;}
    for(i = 1;i <= DMG.VexNums;i++)        //初始化,置U={v}到V-U到各点最短路径;
    {
        flag[i] = 0;
        dist[i] = DMG.Arc[v][i];
    }
    flag[v] = 1;                //v并入U;
    for(i = 1;i <= DMG.VexNums;i++)                
    {
        min = INT_MAX;
        t = i;
        for(j = 1;j <= DMG.VexNums;j++)    //找到U到V-U最小权值(最短路径);
        {
            if(flag[j] == 0 && min > dist[j])
            {
                min = dist[j];
                t = j;
            }
        }
        flag[t] = 1;            //t并入U;
        for(j = 1;j <= DMG.VexNums;j++)    //重置U到V-U各点最短路径;
        {
            if(flag[j] == 0 && dist[t] + DMG.Arc[t][j] < dist[j])
            {
                dist[j] = dist[t] + DMG.Arc[t][j];
            }
        }
    }
    return 0;
}
//========================================================================================
Status Floyd(DMGraph DMG,unsigned int ***flyd)    //Floyd(弗洛伊德)最短路径;
{                                                        int i,j,k,**Path = NULL;
    unsigned int **Weight = NULL;
    if(!(Path = (int **)malloc((DMG.VexNums+1)*sizeof(int*))))
        {printf("/n内存溢出。");return 1;}
    if(!(Weight = (unsigned int **)malloc((DMG.VexNums+1)*sizeof(unsigned int*))))
        {printf("/n内存溢出。");return 1;}
    *flyd = Weight;
    for(i = 1;i <= DMG.VexNums;i++)        //初始化;
    {
        if(!(Path[i] = (int *)malloc((DMG.VexNums+1)*sizeof(int))))
            {printf("/n内存溢出。");return 1;}
        if(!(Weight[i] = (unsigned int *)malloc((DMG.VexNums+1)*sizeof(unsigned int))))
            {printf("/n内存溢出。");return 1;}
        for(j = 1;j <= DMG.VexNums;j++)
        {
            Weight[i][j] = DMG.Arc[i][j];
            Path[i][j] = 0;
        }
    }
    for(k = 1;k <= DMG.VexNums;k++)        //Floyd迭代算法;
        for(i = 1;i <= DMG.VexNums;i++)
            for(j = 1;j <= DMG.VexNums;j++)
                if(Weight[i][j] > (Weight[i][k] + Weight[k][j]))
                {
                    Weight[i][j] = Weight[i][k] + Weight[k][j];
                    Path[i][j] = k;
                }
    for(i = 1;i <= DMG.VexNums;i++)        //输出;
    {
        printf("/n从%3d出发的最短路径:",i);
        for(j = 1;j <= DMG.VexNums;j++)
        {
            if(j != i && Weight[i][j] < INT_MAX)
                printf("/n/t自%3d ==>%3d点:%4d",i,j,Weight[i][j]);
        }
    }
    return 0;
}
//========================================================================================
Status PRN_DMGraph(DMGraph DMG)        //输出邻接矩阵;
{
    int i,j;
    for(i = 1;i <= DMG.VexNums;i++)
    {
        printf("/n/t");
        for(j = 1;j <= DMG.VexNums;j++)
        {
            if(DMG.Arc[i][j] < INT_MAX)    printf(" %3d ",DMG.Arc[i][j]);
            else printf("  ∞ ");
        }                                    
        printf("/n");
    }
    return 0;
}
//========================================================================================
Status PRN_DLGraph(DLGraph DLG)        //输出邻接表;
{
    int i;
    ArcType *p = NULL;
    for(i = 1;i <= DLG.VexNums;i++)
    {
        printf("/n %2d(入度%2d) ==>  ",i,DLG.Vex[i].indgree);
        p = DLG.FirstArc[i];
        while(p != NULL)
        {
            if(p->NextArc)    printf("%2d(%3d) ->",p->Adj.VNode,p->Weight);
            else printf("%2d(%3d) 。",p->Adj.VNode,p->Weight);
            p = p->NextArc;
        }
    }
    return 0;
}

  • 上一篇:二叉树基本操作的程序实现
  • 下一篇:链表基本操作的程序实现