拓扑排序含义:对一个有向无环图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("请依次将顶点数据输入进来\n");
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("请依次将边输入进来\n");
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("动态生成失败\n");
}
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("该图有环\n");
}
}
所有的代码如下:
#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("请依次将顶点数据输入进来\n");
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("请依次将边输入进来\n");
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("\n");
}
}
//拓扑排序
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("动态生成失败\n");
}
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("该图有环\n");
}
}
int main()
{
Graph *G; //申明邻接链表的对象
createGraph(G); //创建邻接链表
printfGraph(*G); //打印该邻接链表
printf("该有向图的拓扑排序如下:");
TopologicalSort(G);
}