C-图算法

有向图

在C语言中,你可以使用数组或结构体来表示有向图。以下是一个简单的例子,其中我们使用邻接矩阵来表示有向图。

首先,我们定义一个常量来表示图中的节点数量。然后,我们定义一个二维数组来作为邻接矩阵,如果节点i和节点j之间存在一条边,那么矩阵的第i行第j列的值就是1,否则就是0。

#include <stdio.h>  
  
#define NODE_COUNT 5  
  
int graph[NODE_COUNT][NODE_COUNT] = {  
    {0, 1, 0, 0, 0},  
    {0, 0, 1, 0, 0},  
    {0, 0, 0, 1, 0},  
    {0, 0, 0, 0, 1},  
    {0, 0, 0, 0, 0}  
};  
  
int main() {  
    for (int i = 0; i < NODE_COUNT; i++) {  
        for (int j = 0; j < NODE_COUNT; j++) {  
            if (graph[i][j] == 1) {  
                printf("存在从节点%d到节点%d的边\n", i, j);  
            } else {  
                printf("不存在从节点%d到节点%d的边\n", i, j);  
            }  
        }  
    }  
  
    return 0;  
}

在这个例子中,我们定义了一个5x5的邻接矩阵来表示一个有向图。然后,我们使用嵌套循环来遍历矩阵中的每个元素,如果元素的值是1,那么我们就打印出一条从节点i到节点j的边。

请注意,这只是一个非常基础的例子。在实际应用中,你可能需要实现更复杂的功能,比如添加边、删除边、查找路径等等。你可能还需要使用更复杂的数据结构,比如邻接表,来更有效地表示和操作图。

此外,你还需要考虑错误处理和边界条件。例如,如果你试图添加一个不存在的节点作为边的终点,那么你的代码应该如何处理这种情况?这些都是在实际编程中需要考虑的问题。

有向图的添加

在C语言中,为有向图添加边通常意味着更新表示图的数据结构以反映新的连接关系。对于有向图,我们通常使用邻接矩阵或邻接表来表示。下面是使用邻接表表示有向图并添加边的示例代码:

#include <stdio.h>  
#include <stdlib.h>  
  
// 定义边的结构体  
typedef struct Edge {  
    int dest; // 边的终点  
    struct Edge* next; // 指向下一条边的指针  
} Edge;  
  
// 定义节点的结构体  
typedef struct Node {  
    int data; // 节点的数据  
    Edge* firstEdge; // 指向第一条边的指针  
} Node;  
  
// 定义图的结构体  
typedef struct Graph {  
    int nodeCount; // 节点数量  
    Node** nodes; // 节点数组  
} Graph;  
  
// 创建新的边  
Edge* createEdge(int dest) {  
    Edge* edge = (Edge*)malloc(sizeof(Edge));  
    edge->dest = dest;  
    edge->next = NULL;  
    return edge;  
}  
  
// 添加边到节点  
void addEdgeToNode(Node* node, int dest) {  
    Edge* newEdge = createEdge(dest);  
    newEdge->next = node->firstEdge;  
    node->firstEdge = newEdge;  
}  
  
// 创建新的节点  
Node* createNode(int data) {  
    Node* node = (Node*)malloc(sizeof(Node));  
    node->data = data;  
    node->firstEdge = NULL;  
    return node;  
}  
  
// 创建图  
Graph* createGraph(int nodeCount) {  
    Graph* graph = (Graph*)malloc(sizeof(Graph));  
    graph->nodeCount = nodeCount;  
    graph->nodes = (Node**)malloc(nodeCount * sizeof(Node*));  
  
    for (int i = 0; i < nodeCount; i++) {  
        graph->nodes[i] = createNode(i);  
    }  
  
    return graph;  
}  
  
// 添加边到图  
void addEdge(Graph* graph, int src, int dest) {  
    if (src < 0 || src >= graph->nodeCount || dest < 0 || dest >= graph->nodeCount) {  
        printf("Invalid source or destination node.\n");  
        return;  
    }  
    addEdgeToNode(graph->nodes[src], dest);  
}  
  
// 打印图  
void printGraph(Graph* graph) {  
    for (int i = 0; i < graph->nodeCount; i++) {  
        printf("Node %d: ", i);  
        Edge* edge = graph->nodes[i]->firstEdge;  
        while (edge != NULL) {  
            printf("%d ", edge->dest);  
            edge = edge->next;  
        }  
        printf("\n");  
    }  
}  
  
// 释放图的内存  
void freeGraph(Graph* graph) {  
    for (int i = 0; i < graph->nodeCount; i++) {  
        Edge* edge = graph->nodes[i]->firstEdge;  
        while (edge != NULL) {  
            Edge* temp = edge;  
            edge = edge->next;  
            free(temp);  
        }  
        free(graph->nodes[i]);  
    }  
    free(graph->nodes);  
    free(graph);  
}  
  
int main() {  
    // 创建一个有向图,包含5个节点  
    Graph* graph = createGraph(5);  
  
    // 添加边到图  
    addEdge(graph, 0, 1); // 添加从节点0到节点1的边  
    addEdge(graph, 1, 2); // 添加从节点1到节点2的边  
    addEdge(graph, 2, 3); // 添加从节点2到节点3的边  
    addEdge(graph, 3, 4); // 添加从节点3到节点4的边  
  
    // 打印图  
    printGraph(graph);  
  
    // 释放图的内存  
    freeGraph(graph);  
  
    return 0;  
}

在这个示例中,我们定义了三个结构体:EdgeNodeGraphEdge结构体表示一条边,包含目标节点的索引和一个指向下一条边的指针。Node结构体表示一个节点,包含节点的数据和指向第一条边的指针。Graph结构体表示整个图,包含节点数量和节点数组的指针。

无向图

在C语言中,无向图通常也是通过邻接矩阵或邻接表来表示的。与有向图不同,无向图的边没有方向性,即如果节点A与节点B之间存在一条边,那么节点B与节点A之间也存在一条边

#include <stdio.h>  
#include <stdlib.h>  
  
#define NODE_COUNT 5  
  
// 定义无向图的结构体  
typedef struct {  
    int matrix[NODE_COUNT][NODE_COUNT];  
} Graph;  
  
// 初始化无向图  
void initializeGraph(Graph *graph) {  
    for (int i = 0; i < NODE_COUNT; i++) {  
        for (int j = 0; j < NODE_COUNT; j++) {  
            graph->matrix[i][j] = 0; // 初始时,所有边都不存在  
        }  
    }  
}  
  
// 添加边到无向图  
void addEdge(Graph *graph, int src, int dest) {  
    // 检查源节点和目标节点是否有效  
    if (src < 0 || src >= NODE_COUNT || dest < 0 || dest >= NODE_COUNT) {  
        printf("Invalid source or destination node.\n");  
        return;  
    }  
    // 由于是无向图,所以需要在矩阵的两个位置都标记边的存在  
    graph->matrix[src][dest] = 1;  
    graph->matrix[dest][src] = 1;  
}  
  
// 打印无向图  
void printGraph(Graph *graph) {  
    for (int i = 0; i < NODE_COUNT; i++) {  
        for (int j = 0; j < NODE_COUNT; j++) {  
            printf("%d ", graph->matrix[i][j]);  
        }  
        printf("\n");  
    }  
}  
  
int main() {  
    Graph graph;  
    initializeGraph(&graph); // 初始化图  
  
    // 添加边到无向图  
    addEdge(&graph, 0, 1); // 添加节点0和节点1之间的边  
    addEdge(&graph, 1, 2); // 添加节点1和节点2之间的边  
    addEdge(&graph, 2, 3); // 添加节点2和节点3之间的边  
    addEdge(&graph, 3, 4); // 添加节点3和节点4之间的边  
    addEdge(&graph, 0, 4); // 添加节点0和节点4之间的边  
  
    // 打印无向图  
    printGraph(&graph);  
  
    return 0;  
}

在这个示例中,我们定义了一个Graph结构体,它包含一个二维数组matrix作为邻接矩阵。initializeGraph函数用于初始化图,将所有边的值设置为0,表示它们不存在。addEdge函数用于添加边,由于是无向图,我们需要在邻接矩阵的两个对应位置上都设置值为1。printGraph函数用于打印图的邻接矩阵表示。

请注意,这个示例中的NODE_COUNT是一个常量,定义了图中节点的数量。在实际应用中,你可能需要根据实际情况动态地创建和管理节点和边。此外,对于大型图,邻接矩阵可能不是最有效的表示方法,因为它会占用大量的内存空间。在这种情况下,你可能需要考虑使用邻接表或其他数据结构来表示图。

无环图--邻接表

在C语言中,邻接表是一种用于表示图的数据结构,特别适用于稀疏图(即边的数量远小于节点数量的平方)。邻接表由一组链表组成,每个链表对应一个节点,链表中存储了与该节点相邻的所有节点。对于无向图,每个链表中的节点通常成对出现,表示两个节点之间的双向连接。

#include <stdio.h>  
#include <stdlib.h>  
  
// 定义边的结构体  
typedef struct Edge {  
    int dest;       // 边的终点  
    struct Edge* next; // 指向下一条边的指针  
} Edge;  
  
// 定义节点的结构体  
typedef struct Node {  
    int data;       // 节点的数据  
    Edge* firstEdge; // 指向第一条边的指针  
} Node;  
  
// 创建新的边  
Edge* createEdge(int dest) {  
    Edge* edge = (Edge*)malloc(sizeof(Edge));  
    edge->dest = dest;  
    edge->next = NULL;  
    return edge;  
}  
  
// 添加边到节点的链表  
void addEdgeToNode(Node* node, int dest) {  
    Edge* newEdge = createEdge(dest);  
    newEdge->next = node->firstEdge;  
    node->firstEdge = newEdge;  
}  
  
// 创建新的节点  
Node* createNode(int data) {  
    Node* node = (Node*)malloc(sizeof(Node));  
    node->data = data;  
    node->firstEdge = NULL;  
    return node;  
}  
  
// 创建图  
Node** createGraph(int nodeCount) {  
    Node** graph = (Node**)malloc(nodeCount * sizeof(Node*));  
    for (int i = 0; i < nodeCount; i++) {  
        graph[i] = createNode(i);  
    }  
    return graph;  
}  
  
// 添加边到图  
void addEdge(Node** graph, int src, int dest) {  
    if (src < 0 || src >= NODE_COUNT || dest < 0 || dest >= NODE_COUNT) {  
        printf("Invalid source or destination node.\n");  
        return;  
    }  
    addEdgeToNode(graph[src], dest);  
    addEdgeToNode(graph[dest], src); // 因为是无向图,所以需要添加双向边  
}  
  
// 打印图  
void printGraph(Node** graph, int nodeCount) {  
    for (int i = 0; i < nodeCount; i++) {  
        printf("Node %d: ", i);  
        Edge* edge = graph[i]->firstEdge;  
        while (edge != NULL) {  
            printf("%d ", edge->dest);  
            edge = edge->next;  
        }  
        printf("\n");  
    }  
}  
  
// 释放图的内存  
void freeGraph(Node** graph, int nodeCount) {  
    for (int i = 0; i < nodeCount; i++) {  
        Edge* edge = graph[i]->firstEdge;  
        while (edge != NULL) {  
            Edge* temp = edge;  
            edge = edge->next;  
            free(temp);  
        }  
        free(graph[i]);  
    }  
    free(graph);  
}  
  
int main() {  
    const int NODE_COUNT = 5; // 图中节点的数量  
    Node** graph = createGraph(NODE_COUNT); // 创建图  
  
    // 添加边到图  
    addEdge(graph, 0, 1); // 添加从节点0到节点1的边  
    addEdge(graph, 1, 2); // 添加从节点1到节点2的边  
    addEdge(graph, 2, 3); // 添加从节点2到节点3的边  
    addEdge(graph, 3, 4); // 添加从节点3到节点4的边  
    addEdge(graph, 0, 4); // 添加从节点0到节点4的边  
  
    // 打印图  
    printGraph(graph, NODE_COUNT);  
  
    // 释放图的内存  
    freeGraph(graph, NODE_COUNT);  
  
    return 0;  
}

在这个示例中,我们定义了两个结构体:EdgeNodeEdge结构体包含一个指向终点的指针和一个指向下一条边的指针。Node结构体包含一个数据字段和一个指向第一条边的指针。

createGraph函数创建一个由Node指针组成的数组,每个Node指针都指向一个新创建的节点。`addEdgeToNode。

有环图

有环图(Cyclic Graph)是指图中存在至少一个环,即至少有一个节点通过一系列边可以回到自己。有环图与无环图(或无向无环图,也称为有向无环图或DAG)相对。

检测有环图通常使用深度优先搜索(DFS)或广度优先搜索(BFS)算法。这些算法通过标记节点的状态(例如,已访问、正在访问)来检测环。如果在DFS中,我们尝试访问一个已经被标记为正在访问的节点,那么图中就存在环。在BFS中,我们可以通过检测队列中是否出现了重复的节点来判断是否存在环。

#include <stdio.h>  
#include <stdlib.h>  
  
#define MAX_VERTICES 100  
  
int graph[MAX_VERTICES][MAX_VERTICES]; // 邻接矩阵表示图  
int visited[MAX_VERTICES]; // 记录节点是否被访问过  
  
// DFS函数,用于检测环  
int dfs(int v, int visited[]) {  
    visited[v] = 1; // 标记为正在访问  
    for (int i = 0; i < MAX_VERTICES; i++) {  
        if (graph[v][i] && !visited[i]) {  
            if (dfs(i, visited)) return 1; // 如果子节点返回1,表示存在环  
        } else if (graph[v][i] && visited[i]) {  
            return 1; // 发现环  
        }  
    }  
    visited[v] = 2; // 标记为已访问  
    return 0;  
}  
  
// 检测图中是否存在环  
int detectCycle() {  
    for (int v = 0; v < MAX_VERTICES; v++) {  
        if (!visited[v]) {  
            if (dfs(v, visited)) return 1; // 如果DFS返回1,表示存在环  
        }  
    }  
    return 0; // 没有环  
}  
  
int main() {  
    // 初始化图  
    // ...  
  
    // 初始化visited数组  
    for (int i = 0; i < MAX_VERTICES; i++) {  
        visited[i] = 0;  
    }  
  
    // 检测环  
    if (detectCycle()) {  
        printf("图中存在环\n");  
    } else {  
        printf("图中不存在环\n");  
    }  
  
    return 0;  
}

在这个示例中,graph数组是一个邻接矩阵,表示图的结构。visited数组用于记录每个节点的访问状态。dfs函数执行深度优先搜索,并在发现环时返回1。detectCycle函数遍历所有节点,并对每个未访问的节点调用dfs函数。如果dfs函数返回1,则表示图中存在环。

请注意,这个示例代码是简化版,它假设图是通过邻接矩阵表示的,并且图中的节点数量不超过MAX_VERTICES。在实际应用中,你可能需要根据具体情况调整代码,例如使用邻接表来表示图,或者处理大型图时动态分配内存。

完全图

完全图(Complete Graph)通常涉及到图的邻接矩阵或邻接表数据结构。完全图是一个简单图,其中每对不同的顶点之间都恰好有一条边相连。对于包含n个顶点的完全图,它将有n(n-1)/2条边(对于无向图)或n(n-1)条弧(对于有向图)。

#include <stdio.h>  
#include <stdlib.h>  
  
#define MAX_VERTICES 100  
  
// 邻接矩阵表示图  
int graph[MAX_VERTICES][MAX_VERTICES];  
  
// 初始化完全图  
void initializeCompleteGraph(int n) {  
    for (int i = 0; i < n; i++) {  
        for (int j = 0; j < n; j++) {  
            // 如果是无向完全图,则任意两点之间都有边  
            graph[i][j] = (i != j);  
        }  
    }  
}  
  
// 打印图  
void printGraph(int n) {  
    for (int i = 0; i < n; i++) {  
        for (int j = 0; j < n; j++) {  
            printf("%d ", graph[i][j]);  
        }  
        printf("\n");  
    }  
}  
  
int main() {  
    int n = 5; // 假设有5个顶点  
    initializeCompleteGraph(n);  
    printGraph(n);  
    return 0;  
}

这段代码定义了一个MAX_VERTICES大小的二维数组graph,用于存储邻接矩阵。initializeCompleteGraph函数初始化这个矩阵以表示一个完全图,即对于n个顶点的图,如果i不等于j,则graph[i][j]为1(表示存在一条边),否则为0。printGraph函数用于打印邻接矩阵。

对于有向完全图,邻接矩阵的初始化会略有不同,因为每个顶点都会指向其他所有顶点,但方向是单向的。因此,对于有向完全图,邻接矩阵将是一个上三角或下三角矩阵,具体取决于边的方向

使用邻接表表示完全图也是可能的,但邻接表通常用于稀疏图,因为它可以更节省空间。对于完全图,邻接表可能不是最有效的表示方法,因为每个顶点的邻接表都将包含所有其他顶点,导致空间浪费。然而,如果确实要使用邻接表,你可以为每个顶点分配一个包含所有其他顶点索引的列表

稠密图

稠密图(Dense Graph)是指边的数量接近或超过顶点数量的平方的图。对于稠密图,使用邻接矩阵来表示图通常是一个高效的选择,因为可以快速地检查任意两个顶点之间是否存在边

#include <stdio.h>  
#include <stdlib.h>  
  
#define MAX_VERTICES 100  
  
// 邻接矩阵表示图  
int graph[MAX_VERTICES][MAX_VERTICES];  
  
// 初始化稠密图  
void initializeDenseGraph(int n) {  
    // 假设这里有一个算法或函数来填充邻接矩阵,表示稠密图  
    // 例如,随机生成边或根据某种规则添加边  
    // 这里仅作为示例,将所有边初始化为0(表示无边)  
    for (int i = 0; i < n; i++) {  
        for (int j = 0; j < n; j++) {  
            graph[i][j] = 0; // 初始时假设没有边  
        }  
    }  
      
    // 添加边的示例(这里仅添加几条边作为演示)  
    graph[0][1] = 1; // 添加从顶点0到顶点1的边  
    graph[1][2] = 1; // 添加从顶点1到顶点2的边  
    // ... 添加更多边 ...  
}  
  
// 打印图  
void printGraph(int n) {  
    for (int i = 0; i < n; i++) {  
        for (int j = 0; j < n; j++) {  
            printf("%d ", graph[i][j]);  
        }  
        printf("\n");  
    }  
}  
  
int main() {  
    int n = 5; // 假设有5个顶点  
    initializeDenseGraph(n);  
    printGraph(n);  
    return 0;  
}

在这个示例中,graph数组是一个二维数组,用于存储邻接矩阵。initializeDenseGraph函数初始化这个矩阵以表示一个稠密图。在这个函数中,你可以根据你的需要来填充矩阵,例如通过随机生成边或根据某种特定的规则来添加边。printGraph函数用于打印邻接矩阵。

对于稠密图,使用邻接矩阵可以方便地进行各种图算法操作,如检查两个顶点之间是否存在边、计算顶点的度等。然而,需要注意的是,对于非常大的图,即使它是稠密的,使用邻接矩阵也可能不是最高效的选择,因为矩阵可能会占用大量的内存空间。在这种情况下,可能需要考虑使用其他数据结构或图算法来优化存储和计算。

稀疏图

稀疏图(Sparse Graph)是指边的数量远远少于顶点数量的平方的图。对于稀疏图,使用邻接表(Adjacency List)来表示图通常是一个更加高效的选择,因为邻接表仅存储实际存在的边,从而可以节省大量的内存空间。

#include <stdio.h>  
#include <stdlib.h>  
  
#define MAX_VERTICES 100  
#define MAX_DEGREE 100 // 假设每个顶点的最大度数为100  
  
// 邻接表节点  
typedef struct AdjacencyNode {  
    int vertex; // 邻接点的索引  
    struct AdjacencyNode* next; // 指向下一个邻接点的指针  
} AdjacencyNode;  
  
// 邻接表  
typedef struct AdjacencyList {  
    AdjacencyNode* head; // 指向第一个邻接点的指针  
} AdjacencyList;  
  
// 创建新的邻接表节点  
AdjacencyNode* createNode(int vertex) {  
    AdjacencyNode* newNode = (AdjacencyNode*)malloc(sizeof(AdjacencyNode));  
    if (!newNode) {  
        printf("Memory allocation failed.\n");  
        exit(1);  
    }  
    newNode->vertex = vertex;  
    newNode->next = NULL;  
    return newNode;  
}  
  
// 添加边到邻接表  
void addEdge(AdjacencyList* list, int vertex) {  
    AdjacencyNode* newNode = createNode(vertex);  
    newNode->next = list->head;  
    list->head = newNode;  
}  
  
// 初始化稀疏图的邻接表  
void initializeSparseGraph(AdjacencyList* graph, int n) {  
    for (int i = 0; i < n; i++) {  
        graph[i].head = NULL; // 将每个顶点的邻接表头初始化为NULL  
    }  
      
    // 假设这里有一个算法或函数来填充邻接表,表示稀疏图  
    // 例如,根据某种规则添加边  
    // 这里仅作为示例,添加几条边  
    addEdge(&graph[0], 1); // 添加从顶点0到顶点1的边  
    addEdge(&graph[1], 2); // 添加从顶点1到顶点2的边  
    // ... 添加更多边 ...  
}  
  
// 打印图  
void printGraph(AdjacencyList* graph, int n) {  
    for (int i = 0; i < n; i++) {  
        printf("Vertex %d: ", i);  
        AdjacencyNode* temp = graph[i].head;  
        while (temp) {  
            printf("%d ", temp->vertex);  
            temp = temp->next;  
        }  
        printf("\n");  
    }  
}  
  
int main() {  
    int n = 5; // 假设有5个顶点  
    AdjacencyList graph[MAX_VERTICES]; // 创建邻接表数组  
    initializeSparseGraph(graph, n); // 初始化稀疏图  
    printGraph(graph, n); // 打印图  
    return 0;  
}

在这个示例中,AdjacencyNode结构体表示邻接表中的节点,包含一个顶点索引和一个指向下一个邻接点的指针。AdjacencyList结构体表示一个顶点的邻接表,包含一个指向第一个邻接点的指针。

createNode函数用于创建新的邻接表节点,addEdge函数用于将边添加到指定顶点的邻接表中。initializeSparseGraph函数初始化稀疏图的邻接表,并根据需要添加边。printGraph函数用于打印每个顶点的邻接表。

对于稀疏图,使用邻接表可以显著减少内存使用,因为只存储实际存在的边。然而,需要注意的是,邻接表在进行某些操作时可能不如邻接矩阵高效,例如检查两个顶点之间是否存在边时可能需要遍历整个邻接表。因此,在选择数据结构时需要根据具体的应用场景和算法需求进行权衡。

拓扑图

拓扑图(Topological Graph)通常指的是一个有向无环图(Directed Acyclic Graph,DAG)。拓扑排序是对DAG的顶点进行线性排序,使得对于每一条有向边 (u, v),均有u(在排序记录中)比v先出现。这种排序只在DAG中存在,因为它需要确保没有环的存在。

#include <stdio.h>  
#include <stdlib.h>  
  
#define MAX_VERTICES 10  
  
typedef struct AdjListNode {  
    int dest;  
    struct AdjListNode* next;  
} AdjListNode;  
  
typedef struct AdjList {  
    AdjListNode* head;  
} AdjList;  
  
typedef struct Graph {  
    int V;  
    AdjList* array;  
    int* inDegree;  
} Graph;  
  
AdjListNode* createNewNode(int dest) {  
    AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));  
    newNode->dest = dest;  
    newNode->next = NULL;  
    return newNode;  
}  
  
Graph* createGraph(int V) {  
    Graph* graph = (Graph*)malloc(sizeof(Graph));  
    graph->V = V;  
  
    graph->array = (AdjList*)malloc(V * sizeof(AdjList));  
    graph->inDegree = (int*)malloc(V * sizeof(int));  
  
    for (int i = 0; i < V; ++i) {  
        graph->array[i].head = NULL;  
        graph->inDegree[i] = 0;  
    }  
  
    return graph;  
}  
  
void addEdge(Graph* graph, int src, int dest) {  
    // Add edge to adjacency list  
    AdjListNode* newNode = createNewNode(dest);  
    newNode->next = graph->array[src].head;  
    graph->array[src].head = newNode;  
  
    // Increment in-degree of destination vertex  
    graph->inDegree[dest]++;  
}  
  
void topologicalSortUtil(Graph* graph, int v, bool visited[], stack* Stack) {  
    visited[v] = true;  
    AdjListNode* pCrawl = graph->array[v].head;  
  
    while (pCrawl) {  
        if (!visited[pCrawl->dest]) {  
            topologicalSortUtil(graph, pCrawl->dest, visited, Stack);  
        }  
        pCrawl = pCrawl->next;  
    }  
  
    // Push current vertex to stack which stores result  
    push(Stack, v);  
}  
  
void topologicalSort(Graph* graph) {  
    stack* Stack = createStack(graph->V);  
  
    bool* visited = (bool*)malloc(graph->V * sizeof(bool));  
    for (int i = 0; i < graph->V; i++) {  
        visited[i] = false;  
    }  
  
    for (int i = 0; i < graph->V; i++) {  
        if (visited[i] == false) {  
            topologicalSortUtil(graph, i, visited, Stack);  
        }  
    }  
  
    // Print contents of stack  
    printf("Topological Sort: ");  
    while (!isEmpty(Stack)) {  
        printf("%d ", pop(Stack));  
    }  
    printf("\n");  
}  
  
// Stack implementation (not shown here for brevity)  
// You would need to implement a stack with push, pop, createStack, and isEmpty functions.  
  
int main() {  
    Graph* graph = createGraph(6);  
    addEdge(graph, 5, 2);  
    addEdge(graph, 5, 0);  
    addEdge(graph, 4, 0);  
    addEdge(graph, 4, 1);  
    addEdge(graph, 2, 3);  
    addEdge(graph, 3, 1);  
  
    topologicalSort(graph);  
  
    // Cleanup code (not shown)  
    // You would need to free the allocated memory for the graph and stack.  
  
    return 0;  
}

注意:上面的代码片段包含了一个未完成的topologicalSort函数,因为它引用了一个未定义的stack数据结构及其相关操作(pushpopcreateStackisEmpty)。为了完整性,你需要实现一个栈数据结构来支持拓扑排序算法。

另外,请注意,这个示例代码片段使用了递归的拓扑排序实现,它可能不是最高效的方法,特别是对于大型图来说。在实际应用中,你可能会更倾向于使用非递归的实现,例如基于队列的Kahn算法,它具有更好的时间和空间复杂度。

这个代码示例还缺少了一些必要的清理工作。

  • 22
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言是一种广泛应用于系统编程和嵌入式开发的高级编程语言。函数指针是C语言中的一个重要概念,它可以指向函数,并且可以通过函数指针来调用函数。快速排序算法是一种常用的排序算法,它的核心思想是通过分治的策略将一个大问题分解为多个小问题,并通过递归的方式解决这些小问题。 下面是C语言中使用函数指针实现快速排序算法的示例代码: ```c #include <stdio.h> // 交换两个元素的值 void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // 快速排序的分区函数 int partition(int arr[], int low, int high) { int pivot = arr[high]; // 选取最后一个元素作为基准 int i = (low - 1); // 定义一个指针,用于指向小于基准的元素 for (int j = low; j <= high - 1; j++) { if (arr[j] < pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[high]); return (i + 1); } // 快速排序函数 void quickSort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); // 将数组分区,并获取分区点的位置 quickSort(arr, low, pi - 1); // 对分区点左边的子数组进行快速排序 quickSort(arr, pi + 1, high); // 对分区点右边的子数组进行快速排序 } } // 打印数组元素 void printArray(int arr[], int size) { for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = {10, 7, 8, 9, 1, 5}; int n = sizeof(arr) / sizeof(arr[0]); printf("原始数组:"); printArray(arr, n); quickSort(arr, 0, n - 1); printf("排序后的数组:"); printArray(arr, n); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值