当前位置: 首页 > news >正文

c语言数据结构--------拓扑排序和逆拓扑排序(Kahn算法和DFS算法实现)

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>


//使用卡恩算法(Kahn)和深度优先算法(DFS)实现

//拓扑排序和逆拓扑排序

//拓扑排序和逆拓扑排序顶点顺序相反

//图,邻接矩阵存储
#define MaxVertexNum 100  //最大顶点数

typedef struct {
    int vex[MaxVertexNum]; //顶点表
    int edge[MaxVertexNum][MaxVertexNum]; //边表
    int vernum, arcnum; //记录当前图的顶点数量和边数
} MGraph;

int vexIndex(MGraph G, int x);

void visit(int i);

//初始化图
MGraph InitMgraph() {
    MGraph graph;
    memset(graph.edge, 0, sizeof(graph.edge));
    graph.arcnum = 0;
    graph.vernum = 0;
    return graph;
}



//带头节点
//链队列节点
typedef struct Linknode {
    int data;
    struct Linknode *next;
} Linknode;

//链队列
typedef struct {
    //队头指针
    Linknode *front;
    //队尾指针
    Linknode *rear;
} LinkQueue;

//初始化队列
void InitQueue(LinkQueue *Q) {
    //创建头结点
    Linknode *temp = (Linknode *) malloc(sizeof(Linknode));
    Q->front = temp;
    Q->rear = temp;
}

//入队
void EnQueue(LinkQueue *Q, int data) {
    //创造节点
    Linknode *temp = (Linknode *) malloc(sizeof(Linknode));
    //赋值
    temp->data = data;
    temp->next = NULL;
    //连接插入节点
    Q->rear->next = temp;
    //队尾指针更换
    Q->rear = temp;
}

//出队
bool DeQueue(LinkQueue *Q, int *e) {
    //队列为空
    if (Q->rear == Q->front) {
        return false;
    }
    //要出队的节点
    Linknode *temp = Q->front->next;
    *e = temp->data;
    //队头指针更换
    Q->front->next = temp->next;
    free(temp);
    //最后一个节点出队
    if (temp == Q->rear) {
        //队尾指针更换
        Q->rear = Q->front;
    }
    return true;
}

/
//借助队列实现拓扑排序
//卡恩算法
bool TopologicalSort(MGraph G) {

    //初始化队列
    LinkQueue *linkQueue = (Linknode *) malloc(sizeof(linkQueue));
    InitQueue(linkQueue);


    //当前顶点的入度
    int indegree[G.vernum];
    //记录拓扑排序
    int print[G.vernum];

    memset(indegree, 0, sizeof(indegree));
    //初始化入度数组
    for (int i = 0; i < G.vernum; ++i) {
        for (int j = 0; j < G.vernum; j++) {
            if (G.edge[j][i] == 1) {
                indegree[i]++;
            }
        }
    }

    //初始化print数组
    memset(print, -1, sizeof(print));

    //度为0的顶点索引入队列
    for (int i = 0; i < G.vernum; i++) {
        if (indegree[i] == 0) {
            EnQueue(linkQueue, i);
            indegree[i] = -1;
        }
    }
    //记录顶点个数
    int count = 0;
    int *e = malloc(sizeof(int));
    while (linkQueue->rear != linkQueue->front) {
        DeQueue(linkQueue, e);
        print[count] = G.vex[*e];

        count++;

        for (int i = 0; i < G.vernum; ++i) {
            if (G.edge[*e][i] == 1) {
                indegree[i]--;
            }

            if (indegree[i] == 0) {
                EnQueue(linkQueue, i);
                indegree[i] = -1;
            }

        }
    }

    if (count < G.vernum)
        return false;
    else {
        for (int i = 0; i < G.vernum; i++) {
            printf("%d  ", print[i]);
        }
        return true;
    }

}

int time;
int finalTime[100];
int visited[100];

//DFS算法实现拓扑排序
//v为入度为0的顶点
void DFSTopologicalSort(MGraph G, int i) {
    //对i做已访问标记
    visited[vexIndex(G, i)] = 1;
    //找到i的所有邻接点
    for (int j = 0; j < G.vernum; j++) {
        if (visited[j] == 0 && G.edge[vexIndex(G, i)][j] == 1) {
            DFSTopologicalSort(G, G.vex[j]);
        }
    }
    (time)++;
    finalTime[vexIndex(G, i)] = time;

}

//使用后visited会被重新赋值,需重置
//建议用一个变量临时保存原有图
void DFSTraverseTopologicalSort(MGraph G, int i) {
    time = 0;
    for (int j = 0; j < G.vernum; j++) {
        visited[j] = 0;
    }
    DFSTopologicalSort(G, i);
    for (int j = 0; j < G.vernum; j++) {
        if (visited[j] == 0) {
            DFSTopologicalSort(G, G.vex[j]);
        }
    }

    for (int j = 0; j < G.vernum; j++) {
        printf("%d  ", finalTime[j]);
    }
}


//有向图深度优先搜索
void niDFSTopologicalSort(MGraph G, int i) {

    //对i做已访问标记
    visited[vexIndex(G, i)] = 1;
    //找到i的所有邻接点
    for (int j = 0; j < G.vernum; j++) {
        if (visited[j] == 0 && G.edge[vexIndex(G, i)][j] == 1) {
            niDFSTopologicalSort(G, G.vex[j]);
        }
    }
    printf("%d  ", i);
}

//使用后visited会被重新赋值,需重置
//建议用一个变量临时保存原有图
//连通图和非连通图的深度优先搜索(改进)
void niDFSTraverseTopologicalSort(MGraph G, int i) {
    for (int j = 0; j < G.vernum; j++) {
        visited[j] = 0;
    }

    niDFSTopologicalSort(G, i);
    for (int j = 0; j < G.vernum; j++) {
        if (visited[j] == 0) {
            niDFSTopologicalSort(G, G.vex[j]);
        }
    }
}


int main(void) {
    //有向图
    //初始化图
    MGraph graph = InitMgraph();
    //图添加元素
    //顶点集添加1,2,3,4,5
    for (int i = 0; i < 5; i++) {
        graph.vex[i] = i + 1;
        graph.vernum++;
    }
    //边集加边<1,2>,<1,4>,<2,3>,<2,4>,<3,5>,<4,3>,<4,5>
    graph.edge[0][1] = 1;
    graph.edge[0][3] = 1;
    graph.edge[1][2] = 1;
    graph.edge[1][3] = 1;
    graph.edge[2][4] = 1;
    graph.edge[3][2] = 1;
    graph.edge[3][4] = 1;
    graph.arcnum = 7;
    printf("拓扑排序序列:\n");
    TopologicalSort(graph);
    printf("\n");
    printf("tineFinal数组:\n");
    DFSTraverseTopologicalSort(graph, 1);
    printf("\n");
    printf("逆拓扑排序序列:\n");
    niDFSTraverseTopologicalSort(graph, 5);
}

//返回x在顶点表的索引
int vexIndex(MGraph G, int x) {
    int index = -1;
    for (int i = 0; i < G.vernum; i++) {
        if (G.vex[i] == x) {
            index = i;
            break;
        }
    }
    return index;
}

测试用例

http://www.dtcms.com/a/108832.html

相关文章:

  • MySQL的安装与初始化流程
  • 联想M7400打印机怎么清零
  • 基于LangChain和通义(Tongyi)实现NL2SQL的智能检索(无需训练)
  • Spring Boot 3.4.3 和 Spring Security 6.4.2 实现基于内存和 MySQL 的用户认证
  • 《Linux内存管理:实验驱动的深度探索》【附录】【实验环境搭建 1】【Qemu 运行 linux 6.0.9】
  • c++函数中的多态是怎样体现的
  • Cursor的主要好处
  • 【排序算法】堆排、快排、归并排、各种排
  • 动态规划 线性dp系列:数字三角形
  • Mysql 中数据主键类型不一样导致数据插入速度快慢问题
  • Java开发如何基于 Spring AI Alibaba 玩转 MCP:从发布、调用到 Claude Manus 集成
  • 2.5路径问题专题:LeetCode 64. 最小路径和
  • Python的三方库之Pandas(三)
  • MetaBase Mysql8.0连接不上
  • 怎么理解量子比特模型,迁移到量子计算机开始编程
  • 飞桨新一代框架3.0正式发布:加速大模型时代的技术创新与产业应用
  • AF3 OpenFoldMultimerDataset类解读
  • 洛谷题单3-P1035 [NOIP 2002 普及组] 级数求和-python-流程图重构
  • JavaScript日期对象
  • Python 编程实战:打造高效便捷的目录结构生成器
  • 踩坑ubuntu24.04 编译vtk9.3.1的安卓版本
  • 前端开发技术演进与就业现实:顺应时代方能不被淘汰-优雅草卓伊凡
  • ubantu执行sudo chown -R username xxx(文件夹)命令失效
  • 推荐系统(二十一):基于MaskNet的商品推荐CTR模型实现
  • OpenCV 图形API(12)用于计算图像或矩阵的平均值函数mean()
  • dify开启多租户模式
  • Coco-AI 支持嵌入,让你的网站拥有 AI 搜索力
  • 基于javaweb的SSM+Maven机房管理系统设计与实现(源码+文档+部署讲解)
  • 智慧高炉厂可视化:钢铁行业的数字化转型之路
  • leetcode31.下一个排列