图论(四)--拓扑排序

基于算法导论图算法-拓扑排序

  • 题目描述
  • 问题分析
  • 源代码
  • 结果截图

    题目描述

    对有向无环图进行拓扑排序(使用队列和DFS分别进行实现)

    问题分析

    1、使用队列进行实现:不断寻找入度为0的点;

    2、使用DFS进行实现:DFS图后根据各顶点发现时间逆序排列,即可得到拓扑排序(证明可以看算法导论第22章22.3节拓扑排序)

伪代码

队列实现
队列实现

DFS实现
DFS实现

源代码

int topSort_queue(Graph G);//队列实现
void topSort_dfs(Graph G);//dfs实现
void print_order_queue(Graph G);//打印拓扑排序序列(queue)
void print_order_dfs(Graph G);//打印拓扑排序序列(dfs)
int TopOrder[VertexNum];

void print_order_queue(Graph G) {
    for (int i = 0; i < G->vexnum; i++) {
        printf("%d ",TopOrder[i]);
    }
    printf("\n");
}

int topSort_queue(Graph G) {//用队列实现拓扑排序,不断寻找入度为0的顶点
    memset(TopOrder, -1, sizeof(TopOrder));
    queue<int> Q;
    int count = 0;
    PtrToNode ptr;
    for (int i = 0; i < G->vexnum; i++) {//将入度为0的顶点进队列
        if (G->vertices[i].in_degree == 0) Q.push(i);
    }
    while (!Q.empty()) {
        int u = Q.front();
        TopOrder[count++] = u;
        Q.pop();
        for (ptr = G->vertices[u].adjto; ptr != NULL; ptr = ptr->next) {//将出队列的顶点相邻的顶点入度减一          
            if (--G->vertices[ptr->adjvex].in_degree == 0) Q.push(ptr->adjvex);
        }
    }
    if (count != VertexNum) return 0;
    else return 1;
}


struct num_finTime {//基于dfs实现拓扑排序时用到的数据结构
    int number;
    int finTime;
};
struct num_finTime TopOrder1[VertexNum];//序列

bool cmp(const struct num_finTime &a1, const struct num_finTime &a2) {
    return a1.finTime > a2.finTime;
}


void print_order_dfs(Graph G) {
    for (int i = 0; i < G->vexnum; i++) {
        printf("%d ", TopOrder1[i].number);
    }
    printf("\n");
}

void topSort_dfs(Graph G) {
    DFS(G);//dfs具体代码可以参考[图论(三)-深度优先搜索(DFS)](http://blog.csdn.net/deep_kang/article/details/70880024)
    for (int i = 0; i < G->vexnum;i++){
        TopOrder1[i].number = i;
        TopOrder1[i].finTime = G->vertices[i].finish_time;
    }
    sort(TopOrder1, TopOrder1 + VertexNum, cmp);//此处可以优化,需要在DFS代码中添加一些细节,在每次结点结束时,将该节点加入到链表头,这样可使算法效率提高(省去了这次排序)
}

int main() {
    CreateRandomDirectGraph();
    Graph G = CreateDirectGraph();//为测试方便,10个顶点
    print_graph(G);//打印图
    //print_VertexDegree(G);//打印顶点度数
    //print_EdgeWeight(G);//打印边权

    printf("拓扑排序:\n");
    if (topSort_queue(G)) {//如果返回1,证明图是有向无环图;除了可以使用拓扑排序求图是否有环,还可以使用DFS(做一点小的改动)具体可参见[判断一个图是否有环 有向图 无向图](http://www.cnblogs.com/xwdreamer/archive/2011/06/11/2297008.html)
        print_order_queue(G);
        topSort_dfs(G);//此处测试dfs实现的代码
        print_order_dfs(G);
    }
    else {
        printf("失败,此图不满足有向无环图。\n");
    }
}

结果截图

两种方式实现的结果不是完全相似,但均是拓扑排序的正确序列,使用链状图结构进行测试可得到完全一致的效果

这里写图片描述

猜你喜欢

转载自blog.csdn.net/deep_kang/article/details/70904234