数据结构:图

数据结构:图

#define INFINITY INT_MAX //整型最大值替代无穷
#define MAX_VERTEX_NUM  20//最大顶点个数

typedef  int VRType; //顶点关系类型
typedef char InfoType; //相关信息类型
typedef char VertexType; //顶点类型

//图的邻接矩阵存储结构
typedef struct
{
    VRType adj; //用1或0表示相邻否
    InfoType *info; //该弧相关信息的指针(可无)
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
    VertexType vexs[MAX_VERTEX_NUM]; //顶点向量
    AdjMatrix arcs; //邻接矩阵
    int vexnum, arcnum; //图的当前顶点数和弧数
}

//图的邻接表存储结构
#define MAX_NAME 3 //顶点字符串最大长度
typedef char VertexType[MAX_NAME]//顶点类型为字符串
typedef struct ArcNode
{
    int adjvex; //该弧所指向的顶点的位置
    struct ArcNode *nextarc;
    InfoType *info;
}ArcNode;
typedef struct VNode
{
    VertexType data; //顶点信息
    ArcNode *firstarc;
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct
{
    AdjList vertices;
    int vexnum, arcnum;
}ALGraph;

//图的十字链表存储结构
typedef struct ArcBox
{ //弧结点
    int tailvex, headvex;
    struct ArcBox *tlink, *hlink;
    InfoType *info;
}ArcBox;
typedef struct VexNode
{//顶点结点
    VertexType data;
    ArcBox *firstin *firstout
}VexNode;
typedef struct{
    VexNode xlist[MAX_VERTEX_NUM];
    int vexnum, arcnum;
}OLGraph;

//无向图的邻接多重表存储结构
enum VisitIf{unvisited, visited};
typedef struct EBox
{
    VisitIf mark; //访问标记
    int ivex, jvex;
    struct EBox *ilink, *jlink;
    InfoType *info;
}EBox;
typedef struct VexBox
{
    VertexType data;
    EBox *firstedge; //指向第一条依附该边的顶点
}VexBox;
typedef struct{
    VexBox adjmulist[MARTEX_VERTEX_NUM];
    int vexnum, edgenum;
}AMLGraph;

Boolean visited[MAX_VERTEX_NUM]; //访问标志数组
void DFS(ALGraph G, int v, void(*Visit)(char*))
{ //从第v个顶点出发递归地深度优先遍历图G。利用邻接表存储结构
    ArcNode *p; //p指向表结点
    visited[v] = true;
    Visit(G.vertices[v].data);
    for(p = G.vertices[v].firstarc; p; p=p->nextarc) //p依次指向v的邻接点
        if(!visited[p->data.adjvex]) //v的邻接顶点尚未访问
            DFS(G, p->data.adjvex, Visit);
}

int LocateVex(ALGraph G, VertexType u)
{ //若图中存在顶点u,则返回该顶点在图中位置,否则返回-1
    int i;
    for(i = 0; i < G.vexnum; i++)
        if(strcmp(u, G.vertices[i].data))
            return i;
    return -1;
}

void DFSTraverse(ALGraph G, void(*Visit)(char *))
{ //对图G作深度优先遍历
    int v;
    for(v = 0; v < G.vexnum; v++) //访问标志数组初始化
        visited[v] = false;
    for(v = 0; v < G.vexnum; v++)
        if(!visited[v])
            DFS(G, v, Visit);
}


void BFSTraverse(ALGraph G, void(*Visit)(char *))
{ //按广度优先非递归遍历图G。使用辅助队列Q, 利用邻接表存储结构
    int v, u;
    ArcNode *p;
    LinkQueue Q; //链队列类型
    for(v = 0; v<G.vexnum; v++)
        visited[v] = false;
    InitQueue(Q);
    for(v = 0; v < G.vexnum; v++)
        if(!visited[v])
        {
            visited[v] = true;
            Visit(G.vertices[v].data);
            EnQueue(Q, v);
            while(!QueueEmpty(Q))
            {
                DeQueue(Q, u);
                for(p = G.vertices[u].firstarc; p; p = p->nextarc)
                    if(!visited[p->data.adjvex])
                    { //u的邻接顶点尚未访问
                        visited[p->data.adjvex] = true;
                        Visit(G.vertices[p->data.adjvex].data);
                        EnQueue(Q, p->data.adjvex); //入队该邻接顶点序号
                    }
            }
        }
}

//最小生成树普里姆算法
typedef struct
{ //记录从顶点集U到V-U的代价最小的边的辅助数组定义
    VertexType adjvex;
    VRType lowcost;
}minside[MAX_VERTEX_NUM]
int minimum(minside SZ, MGraph)
{ //求SZ.lowcost的最小正值,并返回其在SZ中的序号
    int i = 0, k, j, min;
    while(!(SZ[i].lowcost))
        i++;
    min = SZ[i].lowcost; //第一个不为零的值
    k = i;
    for(j = i + 1; j<G.vexnum; j++)
        if(SZ[j].lowcost > 0 && min > SZ[j].lowcost)
        {
            min = SZ[j].lowcost;
            k = j;
        }
    return k;
}
void MiniSpanTree_PRIM(MGraph G, VertexType u)
{ //普里姆算法从第u个顶点出发构造最小生成树,输出T的各条边
    int i, j, k;
    minside closedge;
    k = LocateVex(G,u);
    for(j = 0; j < G.vexnum; j++)
    { //辅助数组初始化
        strcpy(closedge[j].adjvex, u);
        closedge[j].lowcost = G.arcs[k][j].adj;
    }
    closedge[k].lowcost = 0; //初始, U={u}
    printf("最小代价生成树的各条边为\n");
    for(i = 1; i < G.vexnum; ++i)
    { //选择其余G.vexnum-1个顶点
        k = minimum(closedge, G); //求出T的下一个节点:第k顶点
        printf("(%s-%s)\n", closedge[k].adjvex, G.vexs[k]); //输出生成树的边
        closedge[k].lowcost = 0; //第k顶点集并入U集
        for(j = 0; j < G.vexnum; j++)
            if(G.arcs[k][j].adj < closedge[j].lowcost)
            { //新顶点并入U集后重新选最小边
                strcpy(closedge[j].adjvex, G.vexs[k]);
                closedge[j].lowcost = G.arcs[k][j].adj
            }
    }

}

void Kruskal(MGraph G)
{ //克鲁斯卡尔算法求最小生成树, 利用邻接矩阵的存储结构
    int set[MAX_VERTEX_NUM], i, j;
    int k = 0, a = 0, b = 0, min = G.arcs[a][b].adj;
    for(i = 0; i < G.vexnum; i++)
        set[i] = 0; //初态各顶点分别属于各个集合
    printf("最小生成树的各条边为\n");
    while(k < G.vexnum - 1)
    { //最小生成树边数=结点数-1
        for(i = 0; i < G.vexnum; ++i)
            for(j = i +1; j < G.vexnum; ++j) //无向网只在上三角查找
                if(G.[i][j].adj < min)
                {
                    min = G.arcs[i][j].adj;
                    a = i;
                    b = j;
                }
        min = G.arcs[i][j].adj = INFINITY;
        if(set[a] != set[b])
        { //边的两顶点不属于同一集合
            printf("%s-%s\n", G.vexs[a], G.vexs[b]);
            k++; //边数+1
            for(i = 0; i < G.vexnum; i++)
                if(set[i] = set[b])  //将顶点b所在的集合并入顶点a所在集合
                    set[i] = set [a];
        }
    }
}

//拓扑排序 利用邻接表存储结构
void FindInDegree(ALGraph G, int indegree[])
{ //求顶点的入度
    int i;
    ArcNode *p;
    for(i = 0; i < G.vexnum; i++)
        indegree[i] = 0;
    for(i = 0; i < G.vexnum; i++)
    {
        p = G.vertices[i].firstarc;
        while(p)
        {
            indegree[p->data.adjvex]++;
            p = p->nextarc;
        }
    }
}
Status TopologicalSort(ALGraph G)
{ //拓扑排序,若无回路,则输出G的顶点的一个拓扑排序
    int i, k, count;
    int indegree[MAX_VARTEX_NUM];
    Sqstack S;
    ArcNode *p;
    FindInDegree(G, indegree);
    InitStack(S);
    for(i = 0; i < G,vexnum; ++i)
        if(!indegree[i])
            push(S, i);
    while(!StackEmpty(S))
    {
        pop(S, i);
        printf("%s", G.vertices[i].data); //输出i号顶点序号
        ++count;
        for(p = G.vertices[i].firstarc; p; p = p->nextarc)
        {
            k = p->data.adjvex;
            if(!(--indegree[k]))
                push(S, k);
        }
    }
}

//迪杰斯特拉算法求最短路径,利用邻接矩阵存储结构
typedef int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //路径矩阵
typedef int ShortPathTable[MAX_VERTEX_NUM]; //最短距离表
void ShortestPath_DIJ(MGraph G, int v0, PathMatrix P, ShortPathTable D)
{ //v0到其他顶点最短路径P及最短距离D
    int v, i, j, w, min;
    Status final[MAX_VERTEX_NUM]; //辅助矩阵,为true则表示最短距离已求出
    for(v = 0; v < G.vexnum; ++v)
    {
        final[v] = false;
        D[v] = G.arcs[v0][v].adj;
        for(w = 0; w < G.vexnum; ++w)
            P[v0][w] = false; //设初值 没有路径
        if(D[v] < INFINITY) //v0到v有直接路径
            P[v][v0]  = true
    }
    D[v0] = 0;
    final[v0] = true;
    for(i = 1; i < G.vexnum; ++i)
    { //每次求得v0到某个顶点v的最短距离,并将v并入S集
        min = INFINITY;
        for(w = 0; w < G.vexnum; ++w)
            if(!final[w] && D[w] < min)
            {
                v = w;
                min = D[w]
            }
        final[v] = true; //将v并入S集
        for(w = 0; w < G.vexnum; ++w) //根据新并入的顶点,更新不在S集的顶点到v0的举例和路径数组
            if(!final[w] && min < INFINITY && G.arcs[v][w].adj < INFINITY && (min +G.arcs[v][w].adj ) < D[w])
            { //w不属于s集且v0->v->w的距离小于v0->w的距离
                D[w] = min + G.arcs[v][w].adj;
                for(j = 0; j < G.vexnum; ++j) //v0到w的顶点=v0到v经过的顶点+v到w的顶点
                    P[w][j] = P[v][j]
                P[v0][w] = true;
            }
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值