0x00思路
1.前置知识:临接矩阵+图的创建+链表相关知识实现栈
2.算入度函数
3.用头插实现栈
4.再用以个void的功能函数
0x01各个函数实现
对图的一些处理
图结构体声明
typedef struct Graph { char* vexs; int** arcs; int vexNum; int arcNum; }Graph;
图的初始化
Graph* initGraph(int vexNum) { Graph* G = (Graph*)malloc(sizeof(Graph)); G -> vexs = (char*)malloc(sizeof(char) * vexNum); G -> arcs = (int**)malloc(sizeof(int*) * vexNum); for (int i = 0 ; i < vexNum; i++) { G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum); } G -> vexNum = vexNum; G -> arcNum = 0; return G; }
图的创建
void createGraph(Graph* G, char* vexs, int* arcs) { for (int i = 0 ; i < G -> vexNum; i++) { G -> vexs[i] = vexs[i]; for (int j = 0; j < G -> vexNum; j++) { G -> arcs[i][j] = *(arcs + i * G -> vexNum + j); if (G -> arcs[i][j] != 0) G -> arcNum ++; } } G -> arcNum /= 2; }
(为了检查是否创建成功,拓扑本身不需要)图的dfs遍历
void DFS(Graph* G, int* visited, int index) { printf("%c\t", G -> vexs[index]); visited[index] = 1; for (int i = 0; i < G ->vexNum; i++) { if (G -> arcs[index][i] == 1 && !visited[i]) { DFS(G, visited, i); } } }
栈的实现
节点结构体声明
typedef struct Node { int data; struct Node* next; }Node;
栈初始化
Node* initStack() { Node* stack = (Node*)malloc(sizeof(Node)); stack -> data = 0; stack -> next = NULL; return stack; }
查空函数
int isEmpty(Node* stack) { if (stack -> next == NULL) { return 1; } else { return 0; } }
入栈出栈函数
void push(Node* stack, int data) { Node* node = (Node*)malloc(sizeof(Node)); node -> data = data; node -> next = stack -> next; stack -> next = node; stack -> data ++; } int pop(Node* stack) { if (!isEmpty(stack)) { Node* node = stack -> next; stack -> next = node -> next; return node -> data; } else { return -1; } }
功能函数的实现
入度计算
int* findInDegrees(Graph* G) { int* inDegrees = (int*)malloc(sizeof(int) * G -> vexNum); for (int i = 0; i < G -> vexNum; i++) { inDegrees[i] = 0; } for (int i = 0 ; i < G -> vexNum; i++) { for (int j = 0; j < G -> vexNum; j++) { if (G -> arcs[i][j]) inDegrees[j] = inDegrees[j] + 1; } } return inDegrees; }
拓扑功能函数
void topologicalSort(Graph* G) { int index = 0; int* top = (int*)malloc(sizeof(int) * G -> vexNum); int* inDegrees = findInDegrees(G); Node* stack = initStack(); for (int i = 0 ; i < G -> vexNum; i++) { if (inDegrees[i] == 0) { push(stack, i); } } while (!isEmpty(stack)) { int vex = pop(stack); top[index++] = vex; for (int i = 0 ; i < G -> vexNum; i++) { if (G -> arcs[vex][i]) { inDegrees[i] = inDegrees[i] - 1; if (inDegrees[i] == 0) push(stack, i); } } } for (int i = 0; i < index; i++) { printf("%c ", G -> vexs[top[i]]); } printf("\n"); }
main
int main() { Graph* G = initGraph(6); int* visited = (int*)malloc(sizeof(int) * G -> vexNum); for (int i = 0; i < G -> vexNum; i++) visited[i] = 0; int arcs[6][6] = { 0,1,1,1,0,0, 0,0,0,0,0,0, 0,1,0,0,1,0, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,1,1,0 }; createGraph(G, "123456", (int*)arcs); DFS(G, visited, 0); printf("\n"); topologicalSort(G); return 0; }
0x02几个有意思的问题
1.为什么要用栈
ans:1.减少时间复杂度,把入度为0的直接先压栈 2.在while遍历时,不断if入度为0压栈,不为0入度-1,执行一次出栈一个 3.ps相同入度,先入后出
2.为什么要定义top数组
ans:因为你push,pop进去的是下标,这个下标是数字,但是你的图的data不一定是数字,所以需要一个"哈希"数组进行对应,index也是在这里用来给哈系数组下标自增的, 也就是"人形自走数组产生器"哈哈哈哈哈
3.idnex干啥用
ans:如上
4.初始化的艺术
ans:我更倾向于把需要用的东西在main函数准备好,然后哪个函数需要啥,传参传啥,
luciffer更喜欢在需要用到这个东西的函数里面初始化并获取,如创建队列,我认为本质问题还是自己逻辑
不够清楚,我的"客制化盲写代码也会附上"
5.关于任意给个例子测试
ans:图的入度很讲究的,我认为有一定的规律可循(有向拓扑图),不能随便给个入度去跑
0x03Code
规范版
#include <stdio.h> #include <stdlib.h> typedef struct Graph { char* vexs; int** arcs; int vexNum; int arcNum; }Graph; typedef struct Node { int data; struct Node* next; }Node; Node* initStack() { Node* stack = (Node*)malloc(sizeof(Node)); stack -> data = 0; stack -> next = NULL; return stack; } int isEmpty(Node* stack) { if (stack -> next == NULL) { return 1; } else { return 0; } } void push(Node* stack, int data) { Node* node = (Node*)malloc(sizeof(Node)); node -> data = data; node -> next = stack -> next; stack -> next = node; stack -> data ++; } int pop(Node* stack) { if (!isEmpty(stack)) { Node* node = stack -> next; stack -> next = node -> next; return node -> data; } else { return -1; } } int* findInDegrees(Graph* G) { int* inDegrees = (int*)malloc(sizeof(int) * G -> vexNum); for (int i = 0; i < G -> vexNum; i++) { inDegrees[i] = 0; } for (int i = 0 ; i < G -> vexNum; i++) { for (int j = 0; j < G -> vexNum; j++) { if (G -> arcs[i][j]) inDegrees[j] = inDegrees[j] + 1; } } return inDegrees; } void topologicalSort(Graph* G) { int index = 0; int* top = (int*)malloc(sizeof(int) * G -> vexNum); int* inDegrees = findInDegrees(G); Node* stack = initStack(); for (int i = 0 ; i < G -> vexNum; i++) { if (inDegrees[i] == 0) { push(stack, i); } } while (!isEmpty(stack)) { int vex = pop(stack); top[index++] = vex; for (int i = 0 ; i < G -> vexNum; i++) { if (G -> arcs[vex][i]) { inDegrees[i] = inDegrees[i] - 1; if (inDegrees[i] == 0) push(stack, i); } } } for (int i = 0; i < index; i++) { printf("%c ", G -> vexs[top[i]]); } printf("\n"); } Graph* initGraph(int vexNum) { Graph* G = (Graph*)malloc(sizeof(Graph)); G -> vexs = (char*)malloc(sizeof(char) * vexNum); G -> arcs = (int**)malloc(sizeof(int*) * vexNum); for (int i = 0 ; i < vexNum; i++) { G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum); } G -> vexNum = vexNum; G -> arcNum = 0; return G; } void createGraph(Graph* G, char* vexs, int* arcs) { for (int i = 0 ; i < G -> vexNum; i++) { G -> vexs[i] = vexs[i]; for (int j = 0; j < G -> vexNum; j++) { G -> arcs[i][j] = *(arcs + i * G -> vexNum + j); if (G -> arcs[i][j] != 0) G -> arcNum ++; } } G -> arcNum /= 2; } void DFS(Graph* G, int* visited, int index) { printf("%c\t", G -> vexs[index]); visited[index] = 1; for (int i = 0; i < G ->vexNum; i++) { if (G -> arcs[index][i] == 1 && !visited[i]) { DFS(G, visited, i); } } } int main() { Graph* G = initGraph(6); int* visited = (int*)malloc(sizeof(int) * G -> vexNum); for (int i = 0; i < G -> vexNum; i++) visited[i] = 0; int arcs[6][6] = { 0,1,1,1,0,0, 0,0,0,0,0,0, 0,1,0,0,1,0, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,1,1,0 }; createGraph(G, "123456", (int*)arcs); DFS(G, visited, 0); printf("\n"); topologicalSort(G); return 0; }
我的"客制化"版本(阉割
#include <stdio.h> #include <stdlib.h> typedef struct Node{ int data; struct Node *next; }Node; int isempty(Node *D){ if(D -> next == NULL) return 1; if(D -> next != NULL) return 0; } Node* init(){ Node *D = (Node*)malloc(sizeof(Node)); D -> next = NULL; D -> data = 0; return D; } void push(Node *D,int data){ Node *node = (Node*)malloc(sizeof(Node)); node -> next = D -> next; D -> next = node; node -> data = data; D -> data = D -> data + 1; } int pop(Node *D){ int i = D -> next -> data; D -> next = D -> next -> next; return i; } int* findIndegree(int* ljjz){ int *indegree = (int*)malloc(sizeof(int)*4); for(int i = 0;i < 4;i++){ for(int j = 0;j < 4;j++){ if(*(ljjz+i*4+j)!=0){ (*(ljjz+i*4+j))--; (*(indegree+j))++; } } } return indegree; } void topology(int *indegree,Node *stack,char *zifu){ int index = 0; int *ans = (int*)malloc(sizeof(int)*4); for(int i =0;i < 4;i++){ if(indegree[i]==0) push(stack,i); else{ indegree[i]--; } } while(!isempty(stack)){ int i = pop(stack); ans[index++] = i ; for(int i = 0;i < 4; i++){ if(indegree[i]!=0){ indegree[i]--; if(indegree[i]==0){ push(stack,i); } } } } for(int i = 0; i < index; i++){ printf("%c ",zifu[ans[i]] ); } printf("\n"); } int main(){ char *zifu = "ABCD"; int ljjz[4][4] = { 0,1,1,0, 0,0,0,1, 0,1,0,1, 0,0,0,0 }; Node* stack = init(); int *indegree = findIndegree(ljjz); topology(indegree,stack,zifu); }