数据结构复习代码——基于图的邻接表下拓扑排序算法的实现

1、基于图的邻接表下拓扑排序算法的实现

#include<stdio.h>
#include<malloc.h>
#include<assert.h>

#define Default_Vertex_Size 10
#define T char

typedef struct Edge
{
    int dest;
    struct Edge *link;
}Edge;

typedef struct Vertex
{
    T data;
    Edge *adj;
}Vertex;

typedef struct GraphLnk
{
    int MaxVertices;            //最大点数量
    int NumVertices;
    int NumEdges;

    Vertex *NodeTable;
}GraphLnk;


void InitGraph(GraphLnk *g);
void ShowGraph(GraphLnk *g);
void InsertVertex(GraphLnk *g,T v);
void InsertEdge(GraphLnk *g,T v,T w);

void RemoveEgde(GraphLnk *g,T vertex1,T vertex2);
void RemoveVertex(GraphLnk *g,T vertex);
void DestroyGraph(GraphLnk *g);
int GetFirstNeighbor(GraphLnk *g,T vertex);
int GetNextNerghbor(GraphLnk *g,T vertex1,T vertex2);
//拓扑排序
void TopologiclSort(GraphLnk *g);


void TopologiclSort(GraphLnk *g)
{
    int n = g->NumVertices;
    int *count = (int*)malloc(sizeof(int)*n);
    assert(count!=nullptr);

    for(int i=0;i<n;i++)
        count[i] = 0;
    Edge *p;
    for(int i=0;i<n;i++)
    {
        p = g->NodeTable[i].adj;
        while(p!=NULL)
        {
            count[p->dest]++;
            p = p->link;
        }
    }

    /*for(int i=0;i<n;i++)
    {
        printf("%d\n",count[i]);
    }*/
    int top = -1;
    for(int i=0;i<n;++i)
    {
        if(count[i]==0)
        {
            count[i] = top;
            top = i;
        }
    }
    int v,w;
    for(int i=0;i<n;++i)
    {
        if(top==-1)
            printf("有回路!\n");
        else
        {
            v = top;
            top = count[top];
            printf("%c-->",g->NodeTable[v]);
            w = GetFirstNeighbor(g,g->NodeTable[v].data);
            while(w!=-1)
            {
                if(--count[w]==0)
                {
                    count[w] = top;
                    top = w;
                }
                w = GetNextNerghbor(g,g->NodeTable[v].data,g->NodeTable[w].data);
            }
        }
    }


}

//初始化
void InitGraph(GraphLnk *g)
{
    g->MaxVertices = Default_Vertex_Size;
    g->NumEdges = g->NumVertices = 0;

    g->NodeTable = (Vertex*)malloc(sizeof(Vertex)*g->MaxVertices);
    assert(g->NodeTable!=NULL);
    for(int i=0;i<g->MaxVertices;++i)
    {
        g->NodeTable[i].adj = NULL;
    }
}
//输出图结构
void ShowGraph(GraphLnk *g)
{
    Edge *p;
    for(int i=0;i<g->NumVertices;i++)
    {
        p = g->NodeTable[i].adj;
        printf("%d %c:>",i,g->NodeTable[i].data);
        while(p != NULL)
        {
            printf("%d-->",p->dest);
            p = p->link;
        }
        printf("Nul. \n");
    }
}
//插入点结构
void InsertVertex(GraphLnk *g,T v)
{
    if(g->NumVertices>=g->MaxVertices)
        return;
    g->NodeTable[g->NumVertices++].data = v;
}

int GetVertexPos(GraphLnk *g,T v)
{
    for(int i=0;i<g->NumVertices;++i)
        if(g->NodeTable[i].data == v)
            return i;
    return -1;
}
//插入两点之间的边
void InsertEdge(GraphLnk *g,T v,T w)
{
    int v1 = GetVertexPos(g,v);
    int v2 = GetVertexPos(g,w);
    if(v1 == -1 || v2 == -1)
        return;
    Edge *s;
    //V1 -- V2
    s = (Edge*)malloc(sizeof(Edge));
    assert(s!=NULL);
    s->dest = v2;
    s->link = g->NodeTable[v1].adj;     //头插法 进行边节点的插入
    g->NodeTable[v1].adj = s;

    //V2 -- V1
    //s = (Edge*)malloc(sizeof(Edge));
    //assert(s!=NULL);
    //s->dest = v1;
    //s->link = g->NodeTable[v2].adj;
    //g->NodeTable[v2].adj = s;
    g->NumEdges++;
}
//删除两点之间的边
void RemoveEgde(GraphLnk *g,T vertex1,T vertex2)
{
    int v1 = GetVertexPos(g,vertex1);
    int v2 = GetVertexPos(g,vertex2);
    if(v1 == -1 || v2 == -1)
    {
        return;
    }
    Edge *q;
    Edge *p;
    //因为是无向图
    //删除v1 -- v2边
    p = g->NodeTable[v1].adj;
    while(p != NULL && p->dest!=v2)
    {
        q = p;
        p = p->link;
    }
    if(p == NULL)
    {
        return;
    }
    if(q == NULL)
    {
        g->NodeTable[v1].adj = p->link;
    }
    else{
        q->link = p->link;
    }
    free(p);

    //删除v2 -- v1边
    p = g->NodeTable[v2].adj;
    while(p->dest != v1)
    {
        q = p;
        p = p->link;
    }
    if(q == NULL)
    {
        g->NodeTable[v2].adj = p->link;
    }
    else
    {
        q->link = p->link;
    }
    free(p);
    g->NumEdges--;
}
//删除图中的点以及删除与该点相连的边
void RemoveVertex(GraphLnk *g,T vertex)
{
    int v = GetVertexPos(g,vertex);
    if(v == -1)
    {
        return;
    }
    Edge *p = g->NodeTable[v].adj;
    Edge *s;
    Edge *t = NULL;                 //s的前驱
    int k;
    while(p!=NULL)
    {
        k = p->dest;
        s = g->NodeTable[k].adj;
        while(s!=NULL&&s->dest!=v)          //寻找与删除点相关的边的下标
        {
            t = s;
            s = s->link;
        }
        if(s!=NULL)
        {
            if(t==NULL)
            {
                g->NodeTable[k].adj = s->link;
            }
            else
            {
                t->link = s->link;
            }
            free(s);
        }
        g->NodeTable[v].adj = p->link;
        free(p);
        p = g->NodeTable[v].adj;
    }
    g->NumVertices--;
    g->NodeTable[v].data = g->NodeTable[g->NumVertices].data;
    g->NodeTable[v].adj = g->NodeTable[g->NumVertices].adj;

    s = g->NodeTable[v].adj;
    while(s != NULL)
    {
        k = s->dest;
        p = g->NodeTable[k].adj;
        while(p!=NULL)
        {
            if(p->dest == g->NumVertices)
            {
                p->dest = v;
                break;
            }
            p = p->link;
        }
        s = s->link;
    }

}
//摧毁图结构
void DestroyGraph(GraphLnk *g)
{
    Edge *p;
    for(int i=0;i<g->NumVertices;++i)
    {
        p = g->NodeTable[i].adj;
        while(p != NULL)
        {
            g->NodeTable[i].adj = p->link;
            free(p);
            p = g->NodeTable[i].adj;
        }
    }
    free(g->NodeTable);
    g->NodeTable = NULL;
    g->NumVertices = g->NumEdges = g->MaxVertices = 0;
}
//获取第一个邻接顶点
int GetFirstNeighbor(GraphLnk *g,T vertex)
{
    int v = GetVertexPos(g,vertex);
    if(v==-1)
        return -1;
    Edge *p = g->NodeTable[v].adj;
    if(p != NULL)
        return p->dest;
    return -1;
}
//获取某点的下一个邻接点
int GetNextNerghbor(GraphLnk *g,T vertex1,T vertex2)
{
    int v1 = GetVertexPos(g,vertex1);
    int v2 = GetVertexPos(g,vertex2);
    if(v1 ==-1 || v2 == -1)
    {
        return -1;
    }
    Edge *p = g->NodeTable[v1].adj;
    while(p != NULL&& p->dest != v2)
    {
        p = p->link;
    }
    if(p!=NULL && p->link !=NULL)
        return p->link->dest;
    return -1;
}

int main()
{
    GraphLnk gl;
    //初始化
    InitGraph(&gl);
    //插入节点
    InsertVertex(&gl,'A');
    InsertVertex(&gl,'B');
    InsertVertex(&gl,'C');
    InsertVertex(&gl,'D');
    InsertVertex(&gl,'E');
    InsertVertex(&gl,'F');

    InsertEdge(&gl,'A','B');
    InsertEdge(&gl,'A','C');
    InsertEdge(&gl,'A','D');
    InsertEdge(&gl,'C','B');
    InsertEdge(&gl,'C','E');
    InsertEdge(&gl,'D','E');
    InsertEdge(&gl,'F','D');
    InsertEdge(&gl,'F','E');


    ShowGraph(&gl);
    TopologiclSort(&gl);
    printf("Nul.\n");
    ShowGraph(&gl);

    DestroyGraph(&gl);
    return 0;
}

 

posted @ 2022-07-31 10:45  往心。  阅读(31)  评论(0编辑  收藏  举报