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

测试用例

相关推荐
算AI14 小时前
人工智能+牙科:临床应用中的几个问题
人工智能·算法
似水এ᭄往昔15 小时前
【C语言】文件操作
c语言·开发语言
hyshhhh16 小时前
【算法岗面试题】深度学习中如何防止过拟合?
网络·人工智能·深度学习·神经网络·算法·计算机视觉
蒙奇D索大16 小时前
【数据结构】第六章启航:图论入门——从零掌握有向图、无向图与简单图
c语言·数据结构·考研·改行学it
杉之16 小时前
选择排序笔记
java·算法·排序算法
烂蜻蜓17 小时前
C 语言中的递归:概念、应用与实例解析
c语言·数据结构·算法
OYangxf17 小时前
图论----拓扑排序
算法·图论
我要昵称干什么17 小时前
基于S函数的simulink仿真
人工智能·算法
AndrewHZ17 小时前
【图像处理基石】什么是tone mapping?
图像处理·人工智能·算法·计算机视觉·hdr
念九_ysl17 小时前
基数排序算法解析与TypeScript实现
前端·算法·typescript·排序算法