拓扑排序含义:对一个有向无环图G进行拓扑排序,将G中所有顶点构成一个线性序列,对于图中任一顶点v1和v2,如果有弧<v1,v2>属于图G的,则在序列中v1要排在v2前.面,如果该有向无环图满足上述条件,这样的线性表序列就是拓扑排序序列
1.创建结构体
//定义表结点 typedef struct ENode{ int index;//连接顶点的下标 struct ENode *next; }ENode; //表顶点 typedef struct Node{ int in; //入度 char data; //顶点数据 struct ENode *firstNode; //指向表结点的指针 }Node; //邻接链表 typedef struct Graph{ int vexNum; int arcNum; Node vexs[MAX]; }Graph,*myGraph;
2.创建有向无环图
void createGraph(myGraph &G) { G=(Graph*)malloc(sizeof(Graph)); //动态申请空间 int i,j,k; char v1,v2; //边的两个顶点 printf("请输入顶点的数量:"); scanf("%d",&G->vexNum); printf("请输入边的数量:"); scanf("%d",&G->arcNum); printf("请依次将顶点数据输入进来 "); for(i=0;i<G->vexNum;i++) //初始化顶点 { getchar(); scanf("%c",&G->vexs[i].data); G->vexs[i].firstNode=NULL; //初始化为空 G->vexs[i].in=0; //初始化入度为0 } printf("请依次将边输入进来 "); for(i=0;i<G->arcNum;i++) { getchar(); scanf("%c%c",&v1,&v2); j=getLocate(G,v1); //获取下标 k=getLocate(G,v2); //获取下标 ENode *currentNode=(ENode*)malloc(sizeof(ENode)); currentNode->index=k; //顶点下标 currentNode->next=NULL; G->vexs[k].in++; //k的下标入度加1 if(G->vexs[j].firstNode==NULL)//当该顶点没有邻接点时 { G->vexs[j].firstNode=currentNode; //指向这个结点 } else //当该顶点有邻接点时 直接在链的头部进行插入 不是在尾部插入 { ENode *node=G->vexs[j].firstNode; //储存第一个结点 G->vexs[j].firstNode=currentNode; //新节点变成第一个结点 currentNode->next=node; //新的第一个结点指向旧的第一个结点 } } }
3.拓扑排序
void TopologicalSort(myGraph G) //满足栈后进先出的个性 { int top=0; //栈指针 int count=0; //打印次数 ENode *node; //避免 G->vexs[i].firstNode发生改变 int *stack; //栈数组 int getTop; //获取栈顶顶点下标 int i,j; stack=(int*)malloc(G->vexNum*sizeof(int)); //动态生成一个数组 if(!stack) { printf("动态生成失败 "); } for(int i=0;i<G->vexNum;i++) //先将度为0的先入栈 { if(G->vexs[i].in==0) { stack[++top]=i; //储存入栈顶点的下标 ,从top=1开始 } } while(top!=0) //当top等于0时,没有出栈元素了 { int getTop=stack[top--]; //出栈操作 printf("%c ",G->vexs[getTop].data); count++; //用来判断有没有环 for(node=G->vexs[getTop].firstNode;node!=NULL;node=node->next) { j=node->index; //获取顶点的下标 if(!(--G->vexs[j].in)) //如果入度为0则入栈 { stack[++top]=j; } } } if(count<G->vexNum) { printf("该图有环 "); } }
所有的代码如下:
#include<stdio.h> #include<stdlib.h> #define MAX 20 //定义表结点 typedef struct ENode{ int index;//连接顶点的下标 struct ENode *next; }ENode; //表顶点 typedef struct Node{ int in; //入度 char data; //顶点数据 struct ENode *firstNode; //指向表结点的指针 }Node; //邻接链表 typedef struct Graph{ int vexNum; int arcNum; Node vexs[MAX]; }Graph,*myGraph; //获取顶点的下标 int getLocate(myGraph G,char v) { int i; for(i=0;i<G->vexNum;i++) { if(v==G->vexs[i].data) { return i; } } return -1; } //有向的邻接链表的创建 void createGraph(myGraph &G) { G=(Graph*)malloc(sizeof(Graph)); //动态申请空间 int i,j,k; char v1,v2; //边的两个顶点 printf("请输入顶点的数量:"); scanf("%d",&G->vexNum); printf("请输入边的数量:"); scanf("%d",&G->arcNum); printf("请依次将顶点数据输入进来 "); for(i=0;i<G->vexNum;i++) //初始化顶点 { getchar(); scanf("%c",&G->vexs[i].data); G->vexs[i].firstNode=NULL; //初始化为空 G->vexs[i].in=0; //初始化入度为0 } printf("请依次将边输入进来 "); for(i=0;i<G->arcNum;i++) { getchar(); scanf("%c%c",&v1,&v2); j=getLocate(G,v1); //获取下标 k=getLocate(G,v2); //获取下标 ENode *currentNode=(ENode*)malloc(sizeof(ENode)); currentNode->index=k; //顶点下标 currentNode->next=NULL; G->vexs[k].in++; //k的下标入度加1 if(G->vexs[j].firstNode==NULL)//当该顶点没有邻接点时 { G->vexs[j].firstNode=currentNode; //指向这个结点 } else //当该顶点有邻接点时 直接在链的头部进行插入 不是在尾部插入 { ENode *node=G->vexs[j].firstNode; //储存第一个结点 G->vexs[j].firstNode=currentNode; //新节点变成第一个结点 currentNode->next=node; //新的第一个结点指向旧的第一个结点 } } } //打印该邻接表 void printfGraph(Graph G) //打印表不要用指针,这样可能会改变图的结构 { for(int i=0;i<G.vexNum;i++) { printf("%d ",G.vexs[i].in); printf("%c ",G.vexs[i].data); while(G.vexs[i].firstNode!=NULL) { printf("%d ",G.vexs[i].firstNode->index); G.vexs[i].firstNode=G.vexs[i].firstNode->next; } printf(" "); } } //拓扑排序 void TopologicalSort(myGraph G) //满足栈后进先出的个性 { int top=0; //栈指针 int count=0; //打印次数 ENode *node; //避免 G->vexs[i].firstNode发生改变 int *stack; //栈数组 int getTop; //获取栈顶顶点下标 int i,j; stack=(int*)malloc(G->vexNum*sizeof(int)); //动态生成一个数组 if(!stack) { printf("动态生成失败 "); } for(int i=0;i<G->vexNum;i++) //先将度为0的先入栈 { if(G->vexs[i].in==0) { stack[++top]=i; //储存入栈顶点的下标 ,从top=1开始 } } while(top!=0) //当top等于0时,没有出栈元素了 { int getTop=stack[top--]; //出栈操作 printf("%c ",G->vexs[getTop].data); count++; //用来判断有没有环 for(node=G->vexs[getTop].firstNode;node!=NULL;node=node->next) { j=node->index; //获取顶点的下标 if(!(--G->vexs[j].in)) //如果入度为0则入栈 { stack[++top]=j; } } } if(count<G->vexNum) { printf("该图有环 "); } } int main() { Graph *G; //申明邻接链表的对象 createGraph(G); //创建邻接链表 printfGraph(*G); //打印该邻接链表 printf("该有向图的拓扑排序如下:"); TopologicalSort(G); }