无向图的邻接表存储+拓扑排序

 如下是我们要进行拓扑排序的图

 

首先定义好一个节点类和一个边类

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 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值