数据结构复习代码——基于图的邻接表下拓扑排序算法的实现
1、基于图的邻接表下拓扑排序算法的实现
#include<stdio.h> #include<malloc.h> #include<assert.h> #define Default_Vertex_Size 10 #define T char typedef struct Edge { int dest; struct Edge *link; }Edge; typedef struct Vertex { T data; Edge *adj; }Vertex; typedef struct GraphLnk { int MaxVertices; //最大点数量 int NumVertices; int NumEdges; Vertex *NodeTable; }GraphLnk; void InitGraph(GraphLnk *g); void ShowGraph(GraphLnk *g); void InsertVertex(GraphLnk *g,T v); void InsertEdge(GraphLnk *g,T v,T w); void RemoveEgde(GraphLnk *g,T vertex1,T vertex2); void RemoveVertex(GraphLnk *g,T vertex); void DestroyGraph(GraphLnk *g); int GetFirstNeighbor(GraphLnk *g,T vertex); int GetNextNerghbor(GraphLnk *g,T vertex1,T vertex2); //拓扑排序 void TopologiclSort(GraphLnk *g); void TopologiclSort(GraphLnk *g) { int n = g->NumVertices; int *count = (int*)malloc(sizeof(int)*n); assert(count!=nullptr); for(int i=0;i<n;i++) count[i] = 0; Edge *p; for(int i=0;i<n;i++) { p = g->NodeTable[i].adj; while(p!=NULL) { count[p->dest]++; p = p->link; } } /*for(int i=0;i<n;i++) { printf("%d\n",count[i]); }*/ int top = -1; for(int i=0;i<n;++i) { if(count[i]==0) { count[i] = top; top = i; } } int v,w; for(int i=0;i<n;++i) { if(top==-1) printf("有回路!\n"); else { v = top; top = count[top]; printf("%c-->",g->NodeTable[v]); w = GetFirstNeighbor(g,g->NodeTable[v].data); while(w!=-1) { if(--count[w]==0) { count[w] = top; top = w; } w = GetNextNerghbor(g,g->NodeTable[v].data,g->NodeTable[w].data); } } } } //初始化 void InitGraph(GraphLnk *g) { g->MaxVertices = Default_Vertex_Size; g->NumEdges = g->NumVertices = 0; g->NodeTable = (Vertex*)malloc(sizeof(Vertex)*g->MaxVertices); assert(g->NodeTable!=NULL); for(int i=0;i<g->MaxVertices;++i) { g->NodeTable[i].adj = NULL; } } //输出图结构 void ShowGraph(GraphLnk *g) { Edge *p; for(int i=0;i<g->NumVertices;i++) { p = g->NodeTable[i].adj; printf("%d %c:>",i,g->NodeTable[i].data); while(p != NULL) { printf("%d-->",p->dest); p = p->link; } printf("Nul. \n"); } } //插入点结构 void InsertVertex(GraphLnk *g,T v) { if(g->NumVertices>=g->MaxVertices) return; g->NodeTable[g->NumVertices++].data = v; } int GetVertexPos(GraphLnk *g,T v) { for(int i=0;i<g->NumVertices;++i) if(g->NodeTable[i].data == v) return i; return -1; } //插入两点之间的边 void InsertEdge(GraphLnk *g,T v,T w) { int v1 = GetVertexPos(g,v); int v2 = GetVertexPos(g,w); if(v1 == -1 || v2 == -1) return; Edge *s; //V1 -- V2 s = (Edge*)malloc(sizeof(Edge)); assert(s!=NULL); s->dest = v2; s->link = g->NodeTable[v1].adj; //头插法 进行边节点的插入 g->NodeTable[v1].adj = s; //V2 -- V1 //s = (Edge*)malloc(sizeof(Edge)); //assert(s!=NULL); //s->dest = v1; //s->link = g->NodeTable[v2].adj; //g->NodeTable[v2].adj = s; g->NumEdges++; } //删除两点之间的边 void RemoveEgde(GraphLnk *g,T vertex1,T vertex2) { int v1 = GetVertexPos(g,vertex1); int v2 = GetVertexPos(g,vertex2); if(v1 == -1 || v2 == -1) { return; } Edge *q; Edge *p; //因为是无向图 //删除v1 -- v2边 p = g->NodeTable[v1].adj; while(p != NULL && p->dest!=v2) { q = p; p = p->link; } if(p == NULL) { return; } if(q == NULL) { g->NodeTable[v1].adj = p->link; } else{ q->link = p->link; } free(p); //删除v2 -- v1边 p = g->NodeTable[v2].adj; while(p->dest != v1) { q = p; p = p->link; } if(q == NULL) { g->NodeTable[v2].adj = p->link; } else { q->link = p->link; } free(p); g->NumEdges--; } //删除图中的点以及删除与该点相连的边 void RemoveVertex(GraphLnk *g,T vertex) { int v = GetVertexPos(g,vertex); if(v == -1) { return; } Edge *p = g->NodeTable[v].adj; Edge *s; Edge *t = NULL; //s的前驱 int k; while(p!=NULL) { k = p->dest; s = g->NodeTable[k].adj; while(s!=NULL&&s->dest!=v) //寻找与删除点相关的边的下标 { t = s; s = s->link; } if(s!=NULL) { if(t==NULL) { g->NodeTable[k].adj = s->link; } else { t->link = s->link; } free(s); } g->NodeTable[v].adj = p->link; free(p); p = g->NodeTable[v].adj; } g->NumVertices--; g->NodeTable[v].data = g->NodeTable[g->NumVertices].data; g->NodeTable[v].adj = g->NodeTable[g->NumVertices].adj; s = g->NodeTable[v].adj; while(s != NULL) { k = s->dest; p = g->NodeTable[k].adj; while(p!=NULL) { if(p->dest == g->NumVertices) { p->dest = v; break; } p = p->link; } s = s->link; } } //摧毁图结构 void DestroyGraph(GraphLnk *g) { Edge *p; for(int i=0;i<g->NumVertices;++i) { p = g->NodeTable[i].adj; while(p != NULL) { g->NodeTable[i].adj = p->link; free(p); p = g->NodeTable[i].adj; } } free(g->NodeTable); g->NodeTable = NULL; g->NumVertices = g->NumEdges = g->MaxVertices = 0; } //获取第一个邻接顶点 int GetFirstNeighbor(GraphLnk *g,T vertex) { int v = GetVertexPos(g,vertex); if(v==-1) return -1; Edge *p = g->NodeTable[v].adj; if(p != NULL) return p->dest; return -1; } //获取某点的下一个邻接点 int GetNextNerghbor(GraphLnk *g,T vertex1,T vertex2) { int v1 = GetVertexPos(g,vertex1); int v2 = GetVertexPos(g,vertex2); if(v1 ==-1 || v2 == -1) { return -1; } Edge *p = g->NodeTable[v1].adj; while(p != NULL&& p->dest != v2) { p = p->link; } if(p!=NULL && p->link !=NULL) return p->link->dest; return -1; } int main() { GraphLnk gl; //初始化 InitGraph(&gl); //插入节点 InsertVertex(&gl,'A'); InsertVertex(&gl,'B'); InsertVertex(&gl,'C'); InsertVertex(&gl,'D'); InsertVertex(&gl,'E'); InsertVertex(&gl,'F'); InsertEdge(&gl,'A','B'); InsertEdge(&gl,'A','C'); InsertEdge(&gl,'A','D'); InsertEdge(&gl,'C','B'); InsertEdge(&gl,'C','E'); InsertEdge(&gl,'D','E'); InsertEdge(&gl,'F','D'); InsertEdge(&gl,'F','E'); ShowGraph(&gl); TopologiclSort(&gl); printf("Nul.\n"); ShowGraph(&gl); DestroyGraph(&gl); return 0; }