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;
}

测试用例

相关推荐
Felven31 分钟前
A. Everybody Likes Good Arrays!
数据结构·算法
小智学长 | 嵌入式1 小时前
单片机-89C51部分:4、固件烧录
c语言·单片机·嵌入式硬件
AI_RSER1 小时前
基于 Google Earth Engine 的南京江宁区土地利用分类(K-Means 聚类)
算法·机器学习·分类·kmeans·聚类·遥感·gee
Small踢倒coffee_氕氘氚2 小时前
是否应该禁止危险运动论文
经验分享·笔记·算法·灌灌灌灌
simple_whu2 小时前
C语言标准库函数setlocale用法详解
c语言
京东云开发者3 小时前
行稳、致远 | 技术驱动下的思考感悟
算法
Dignity_呱3 小时前
记一次手撕算法面试
前端·算法·面试
CodeJourney.3 小时前
深度探索:DeepSeek赋能WPS图表绘制
数据库·人工智能·算法·信息可视化·excel
陈奕昆3 小时前
6.1腾讯技术岗2025面试趋势前瞻:大模型、云原生与安全隐私新动向
算法·安全·云原生·面试·腾讯
ゞ 正在缓冲99%…3 小时前
leetcode66.加一
java·数据结构·算法