如下是我们要进行拓扑排序的图
首先定义好一个节点类和一个边类
class VertexIndegree():
def __init__(self,data):
self.data=data
self.indegree=0
self.FirstEdge=None
class Edge():
def __init__(self,adjvex):
self.adjvex=adjvex
self.next=None
对于节点类中,data存储节点的值,indegree存储节点的入度(以该顶点为弧头的边的数量)
FirstEdge指向的是该顶点的邻接表。对于边类,adjvex存储的是该节点在节点数组中的index
next指向下一个节点。
定义 main类
class Main():
def __init__(self,Vexs,Edges):
self.vexlist=[]
for vex in Vexs:
self.vexlist.append(VertexIndegree(vex))
self.edges=Edges
传入一个顶点数组Vexs和一个边数组Edges,其中Vexs,Edges的定义如下:
vers = ['A', 'B', 'C', 'D', 'E', 'F','G']
edges = [['A', 'B'], ['A', 'C'], ['A', 'D'],['C','F'] ,['B', 'G'], ['G', 'F'], ['D', 'C'], ['E', 'F'], ['D', 'E']]
注:['A','B']表示以A为弧尾B为弧头。
定义一个获取指定data在Vexs数组中下标的函数:
def Getindex(self,vex):
i=0
for temp in self.vexlist:
if vex==temp.data:
return i
i+=1
注:这个函数比较简单我就不做过多赘述了
定义一个为顶点创造边的函数,也不能说是创造吧,应该是把所有顶点联系起来。
def CreateEdgeforvex(self):
for edg in self.edges:
tail=edg[0] #获取弧尾元素
head=edg[1] #获取弧头元素
postail=self.Getindex(tail) #获取弧头元素在Vexs中的index
poshead=self.Getindex(head)
if self.vexlist[postail].FirstEdge==None:
self.vexlist[postail].FirstEdge=Edge(poshead)
self.vexlist[poshead].indegree+=1
else:
tNode=self.vexlist[postail].FirstEdge #获取FirstEdge
while tNode.next!=None: #直到找到邻接表的最后一个节点
tNode=tNode.next
tNode.next=Edge(poshead)
self.vexlist[poshead].indegree += 1 #弧头顶点的入度加一
结合一下邻接表来解释:
注:其中的info可以存储一些边的信息,比如边的权重。
定义遍历图的函数:
def Traverse(self):
for vex in self.vexlist:
print(f'{vex.data}:节点入度为{vex.indegree}',end='->')
temp=vex.FirstEdge
if temp==None:
print('None',end='')
while temp!=None:
print(self.vexlist[temp.adjvex].data,end=' ')
temp=temp.next
print()
遍历和可得如下结果:
A:节点入度为0->B C D
B:节点入度为1->G
C:节点入度为2->F
D:节点入度为1->C E
E:节点入度为1->F
F:节点入度为3->None
G:节点入度为1->F
注:->后面表示的是A顶点指向的顶点。
拓扑排序算法:
def TopologicalSort(self):
stack=[]
tempvexs=self.vexlist
for vex in tempvexs:
if vex.indegree==0:
stack.append(vex)
while len(stack)!=0:
vex=stack.pop()
print(vex.data,end=' ')
nextvex=vex.FirstEdge
while nextvex!=None:
tempvexs[nextvex.adjvex].indegree-=1
if tempvexs[nextvex.adjvex].indegree==0:
stack.append(tempvexs[nextvex.adjvex])
nextvex=nextvex.next
注:看代码前先去把拓扑算法是怎么做的搞明白来
这个算法中的代码我一行一行给大家解释:
第二行:定义了一个stack列表,用来存储入度为零的顶点。
第三行:复制一下顶点数组,防止接下来的操作对原来图的结构造成破坏
四五六行:遍历顶点数组,将入度为零的节点加入到stack中(入栈)
第七行:设置循环结束的条件
第8,9行:取出栈顶元素,并将其打印出来(这是我们拓扑排序的第一个元素)
第10行:获取刚刚打印出来的顶点的邻接表,比如刚刚打印出来的是顶点A那么就获取顶点A的邻接表,该邻接表中存储了与A有关系的顶点B,C,D
第11行:略
第12行:因为刚刚已经将A打印出来了,相当于将A顶点删除了,所以 B,C,D的入度就要减一。
第13行:做一个判断,如果该顶点的入度为0,则将其加入到stack,为接下来的打印做准备
第14行:继续对与A有关的下一个顶点做相同的操作,比如刚刚已经操作完B了,那么经过这行代码,就转为了对C进行操作。
我这个代码写的是不是有一点递归的味道?
以下是拓扑排序后的输出:
A D E C B G F