zoukankan      html  css  js  c++  java
  • 图的拓扑排序

    拓扑排序

    拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在一条从viv_ivjv_j的路径,那么在排序中vjv_j出现在viv_i的后面。如果图含有圈,那么拓扑排序是不可能的。此外,排序不必是唯一的;任何合理的排序都是可以的。

    算法思想

    第1种

    先找出任意一个没有入边的顶点。然后显示出该顶点,并将它和它的边一起从图中删除。然后对图的其余部分应用同样的方法处理。

    伪代码

    void Topsort(Graph G)
    {
        int Counter;
        Vertex V, W;
    
        for(Counter = 0; Counter < NumVertex; Counter++)
        {
            V = FindNewVertexOfIndegreeZero();
            if(V == NotAVertex)
            {
                Error("Graph has a cycle");
                break;
            }
            TopNum[V] = Counter;    // 或打印出
            for each W adjancent to V
                Indegree[W]--;
        }
    }
    

    函数FindNewVertexOfIndegreeZero扫描Indegree数组,寻找一个尚未被分配拓扑编号的入度为0的顶点;因为其是对Indegree数组的一个简单的顺序扫描,所以每次对它的调用都花费O(V)O(left | V ight |)的时间.由于有Vleft | V ight |这样的调用,因此该算法的运行时间为O(V2)O({left | V ight |}^2)

    第2种

    首先,对每一个顶点计算它的入度(可以在输入图时就计算)。然后将所以入度为0的顶点放入一个初始为空的的队列中。当队列不空时,删除一个顶点vv,并将vv邻接的所有的顶点的入度减1.只要1个顶点的入度将为0,就把该顶点放入队列中。此时,拓扑排序就是顶点出队的顺序。

    C语言代码

    void Topsort(ALGraph G)
    {
        Queue Q;
        int Counter;
        VertexType V;
        ArcNode W;
    
        Q = CreateQueue(MVNum);
        Counter = 0;
    
        for (V = 1; V <= G->vexnum; V++)
            if (G->Indegree[V] == 0)
                Enqueue(V, Q);
    
        while (!IsEmpty(Q))
        {
            V = FrontAndDequeue(Q);
            printf("%d->", V);
            Counter++;
    
            W = G->vertices[V].firstarc;
            while (W != NULL)
            {
                if (--G->Indegree[W->adjvex] == 0)
                    Enqueue(W->adjvex, Q);
                W = W->nextarc;
            }
        }
        printf("^
    ");
    
        if (Counter != G->vexnum)
            printf("Graph has a cycle
    ");
    
        DisposeQueue(Q);
    }
    

    如果使用邻接表,那么执行这个算法所用的时间为O(E+V)O(left | E ight | +left | V ight | )

    完整C语言代码

    #include <stdio.h>
    #include <stdlib.h>
    
    #define NotAVertex (-1)
    #define MVNum (10) // 最大顶点数
    typedef int VertexType;
    typedef int ArcType;
    
    typedef struct ArcNode // 边结点
    {
        VertexType adjvex;       // 该边所指向的顶点的位置
        struct ArcNode *nextarc; // 指向下一条边的指针
        ArcType weight;          // 边的权值
    } * ArcNode;
    
    typedef struct VNode // 顶点信息
    {
        // VertexType data;
        ArcNode firstarc;    // 指向第一条依附该顶点的边的指针
    } VNode, AdjList[MVNum]; // AdjList 表示邻接类型
    
    typedef struct // 邻接表
    {
        AdjList vertices;
        int vexnum, arcnum;  // 图的当前定点数和边数
        int Indegree[MVNum]; // 每个顶点的入度
    } * ALGraph;
    
    void CreateUDG(ALGraph G)
    {
        int i, j;
        int v1, v2;
        ArcNode p1, p2;
        ArcType weight;
    
        printf("Input vexnum: ");
        scanf("%d", &G->vexnum);
        printf("Input arcnum: ");
        scanf("%d", &G->arcnum);
    
        // 输入各点,构造表头结点表
        for (i = 1; i <= G->vexnum; i++)
        {
            G->vertices[i].firstarc = NULL;
            G->Indegree[i] = 0;
        }
    
        // 输入一条边依附的两个顶点
        for (j = 0; j < G->arcnum; j++)
        {
            scanf("%d%d%d", &v1, &v2, &weight);
            p1 = (ArcNode)malloc(sizeof(*p1));
            if (p1 == NULL)
                exit(0);
            p1->adjvex = v2;
            p1->weight = weight;
            p1->nextarc = G->vertices[v1].firstarc;
            G->vertices[v1].firstarc = p1;
            G->Indegree[v2] += 1;
            /*p2 = (ArcNode)malloc(sizeof(struct ArcNode));
            p2->adjvex = i;
            p2->nextarc = G->vertices[j].firstarc;
            G->vertices[j].firstarc = p2;
            G->Indegree[v1] += 1;*/
        }
    }
    
    ALGraph CreateGraph(void)
    {
        ALGraph G;
        G = (ALGraph)malloc(sizeof(*G));
        if (G == NULL)
            exit(0);
        return G;
    }
    
    typedef VertexType ElementType;
    typedef struct QueueNode *Queue;
    struct QueueNode
    {
        ElementType Array[MVNum];
        int Capacity;
        int Size;
        int Front;
        int Rear;
    };
    int IsFull(Queue Q)
    {
        return Q->Size == Q->Capacity;
    }
    int IsEmpty(Queue Q)
    {
        return Q->Size == 0;
    }
    
    Queue CreateQueue(int Capacity)
    {
        Queue Q;
        Q = (Queue)malloc(sizeof(struct QueueNode));
        if (Q == NULL)
            exit(0);
        Q->Capacity = Capacity;
        Q->Size = 0;
        Q->Front = 1;
        Q->Rear = 0;
        return Q;
    }
    
    void Enqueue(ElementType X, Queue Q)
    {
        if (IsFull(Q))
        {
            printf("The queue is full
    ");
            system("pause");
            exit(0);
        }
        Q->Size++;
        if (++Q->Rear == Q->Capacity)
            Q->Rear = 0;
        Q->Array[Q->Rear] = X;
    }
    
    void Dequeue(Queue Q)
    {
        if (IsEmpty(Q))
        {
            printf("The queue is empty
    ");
            system("pause");
            exit(0);
        }
        Q->Size--;
        if (++Q->Front == Q->Capacity)
            Q->Front = 0;
    }
    
    ElementType Front(Queue Q)
    {
        if (IsEmpty(Q))
        {
            printf("The queue is empty
    ");
            system("pause");
            exit(0);
        }
        return Q->Array[Q->Front];
    }
    
    ElementType FrontAndDequeue(Queue Q)
    {
        if (IsEmpty(Q))
        {
            printf("The queue is empty
    ");
            system("pause");
            exit(0);
        }
        Q->Size--;
        return Q->Array[(Q->Front++) % Q->Capacity];
    }
    
    void DisposeQueue(Queue Q)
    {
        free(Q);
    }
    
    void Topsort(ALGraph G)
    {
        Queue Q;
        int Counter;
        VertexType V;
        ArcNode W;
    
        Q = CreateQueue(MVNum);
        Counter = 0;
    
        for (V = 1; V <= G->vexnum; V++)
            if (G->Indegree[V] == 0)
                Enqueue(V, Q);
    
        while (!IsEmpty(Q))
        {
            V = FrontAndDequeue(Q);
            printf("%d->", V);
            Counter++;
    
            W = G->vertices[V].firstarc;
            while (W != NULL)
            {
                if (--G->Indegree[W->adjvex] == 0)
                    Enqueue(W->adjvex, Q);
                W = W->nextarc;
            }
        }
        printf("^
    ");
    
        if (Counter != G->vexnum)
            printf("Graph has a cycle
    ");
    
        DisposeQueue(Q);
    }
    
    int main()
    {
        ALGraph G;
        G = CreateGraph();
        CreateUDG(G);
        Topsort(G);
        system("pause");
        return 0;
    }
    

    输入/输出

    顶点按数字编号,第3个数子为边上的权值。

    Input vexnum: 7
    Input arcnum: 12
    1 2 1
    1 3 1
    3 6 1
    7 6 1
    5 7 1
    2 5 1
    1 4 1
    2 4 1
    5 4 1
    4 7 1
    4 6 1
    4 3 1
    1->2->5->4->3->7->6->^
    请按任意键继续. . .
    
    不一定每天 code well 但要每天 live well
  • 相关阅读:
    虚拟主机导入MySQL出现Unknown character set: ‘utf8mb4’
    解决导入MySQL数据库提示"Unknown character set: 'utf8mb4'"错误
    在js中怎样获得checkbox里选中的多个值?
    CSharp设计模式读书笔记(0):设计原则(学习难度:★★☆☆☆,使用频率:★★★★★)
    how to install maven and svn plugin into eclipse 3.6
    三个月不编程,能力下降80%
    maven管理的struts2spring3mybatisfreemarker框架整合
    Wiki: JavaHL for subversion & ubuntu lucid
    重装系统要装的库包 for ubuntu lucid
    Q for Eclipse is an Apache Maven plugin for the Eclipse IDE
  • 原文地址:https://www.cnblogs.com/geekfx/p/12423055.html
Copyright © 2011-2022 走看看