Python 使用邻接列表实现图形表示时要使用哪种数据结构

Python 使用邻接列表实现图形表示时要使用哪种数据结构,python,data-structures,graph,adjacency-list,Python,Data Structures,Graph,Adjacency List,我有一个非常大的图,大约1000000个节点和许多边。这就是我想要知道的,在实现邻接列表时,哪种数据结构最适合。以下是我一直跟踪的对象 边缘列表 节点到节点连接列表 我使用python进行编码,所以我使用了一个集合(因为根据它,平均插入时间为o(1))作为边缘列表,使用了一个字典作为节点到节点的连接列表(通过使它完全可根据上下文进行散列)。这是我的密码 class node: def __init__(self, name = ""): self.__name = n

我有一个非常大的图,大约1000000个节点和许多边。这就是我想要知道的,在实现邻接列表时,哪种数据结构最适合。以下是我一直跟踪的对象

  • 边缘列表
  • 节点到节点连接列表
我使用python进行编码,所以我使用了一个集合(因为根据它,平均插入时间为o(1))作为边缘列表,使用了一个字典作为节点到节点的连接列表(通过使它完全可根据上下文进行散列)。这是我的密码

class node:
    def __init__(self, name = ""):
        self.__name = name

    def getName(self):
        return self.__name

    def __str__(self):
        return self.__name

    def __hash__(self):
        return hash(self.__name)

    def __lt__(self, other):
        if(type(self) != type(other)):
            return NotImplemented
        return self.__name.__lt__(other.__name)

    def __eq__(self, other):
        if(type(self)) != type(other):
            return NotImplemented
        return self.__name  == other.__name

class Edge:
    def __init__(self, name = "", node1 = None, node2 = None, weight = 0):
        self.__name = name
        self.__firstNode = node1
        self.__secondNode = node2
        self.__weight = weight

    def getName(self):
        return self.__name

    def getFirstNode(self):
        return self.__firstNode

    def getSecondNode(self):
        return self.__secondNode

    def getWeight(self):
        return self.__weight

    def __lt__(self, other):
        if(type(self) != type(other)):
            return NotImplemented
        return self.__name.__lt__(other.__name) and self.__firstNode.__lt__(other.__firstNode) and self.__secondNode.__lt__(other.__secondNode) and self.__weight.__lt__(other.__weight)

    def __eq__(self, other):
        if(type(self) != type(other)):
            return NotImplemented
        return self.__name == other.__name and self.__firstNode == other.__firstNode and self.__secondNode == other.__secondNode and self.__weight == other.__weight

    def __str__(self):
        return self.__name + " " + str(self.__firstNode) + " " + str(self.__secondNode) + " " + str(self.__weight)

    def __hash__(self):
        return hash(hash(self.__name) + hash(self.__firstNode) + hash(self.__secondNode) + hash(self.__weight))

class graph:
    def __init__(self):
        self.__nodeToNode = {}
        self.__edgeList = set()

    def addEdge(self, edge):
        if(type(edge) != type(Edge())):
            return False

        self.__edgeList.add(edge)
        if(not edge.getFirstNode() in self.__nodeToNode):
            self.__nodeToNode[edge.getFirstNode()] = set()

        self.__nodeToNode[edge.getFirstNode()].add(edge.getSecondNode())
        if(not edge.getSecondNode() in self.__nodeToNode):
            self.__nodeToNode[edge.getSecondNode()] = set()

        self.__nodeToNode[edge.getSecondNode()].add(edge.getSecondNode())
        return True
    def getNodes(self):
        return dict(self.__nodeToNode)
    def getEdges(self):
        return set(self.__edgeList)


import string
import random
import time

grp = graph()
nodes = [None] * 20000
for i in range(20000):
    st = ''.join(random.SystemRandom().choice(string.ascii_letters) for i in range(10))
    node1 = node(st)
    nodes[i] = node1

current = time.time()
for i in range(3000000):
    rdm = random.randint(0, 199)
    rdm2 = random.randint(0, 199)
    st = ''.join(random.SystemRandom().choice(string.ascii_letters) for i in range(10))
    eg = Edge(st, nodes[rdm], nodes[rdm2])
    grp.addEdge(eg)

last = time.time()

print((last - current))

nodes = grp.getNodes()
edges = grp.getEdges()

但是这段代码运行得很慢,我能让它更快吗?如果是,请使用什么数据结构?

让我介绍一种创建邻接列表的方法:

假设您有如下输入:

4 4
1 2
3 2
4 3
1 4
4 4
1 2 3 # edge(1, 2) has the weight of 3
3 2 1
4 3 1
1 4 2

input = sys.stdin.read()
data = list(map(int, input.split()))
n, m = data[0:2]
data = data[2:]
edges = list(zip(zip(data[0:(3 * m):3], data[1:(3 * m):3]), data[2:(3 * m):3]))
data = data[3 * m:]
adj = [[] for _ in range(n)]
cost = [[] for _ in range(n)]
for ((a, b), w) in edges:
    adj[a - 1].append(b - 1)
    cost[a - 1].append(w)
第一行包含两个数字
V
E
,下一行
E
定义了两个顶点之间的边

您可以创建一个.txt文件并读取输入,也可以通过
sys.stdin.read()
直接键入:

让我们输出邻接列表
adj

>>> print(adj)
[[1, 3], [0, 2], [1, 3], [2, 0]]
adj[0]
有两个adj节点:1和3。这意味着节点1有两个adj节点:2和4

现在,如果您想要一个有向加权图,只需修改如下输入:

4 4
1 2
3 2
4 3
1 4
4 4
1 2 3 # edge(1, 2) has the weight of 3
3 2 1
4 3 1
1 4 2

input = sys.stdin.read()
data = list(map(int, input.split()))
n, m = data[0:2]
data = data[2:]
edges = list(zip(zip(data[0:(3 * m):3], data[1:(3 * m):3]), data[2:(3 * m):3]))
data = data[3 * m:]
adj = [[] for _ in range(n)]
cost = [[] for _ in range(n)]
for ((a, b), w) in edges:
    adj[a - 1].append(b - 1)
    cost[a - 1].append(w)
将权重存储在
成本中,例如,
成本[0][1]
=3,
成本[0][3]
=2


希望这有帮助

您是想自己编写代码,还是对第三方解决方案感到满意?如果是,您可能需要查看图形数据库Neo4j(),或者python图形包。@Jaco我会检查它,但这是学校项目,我必须自己使用networkx库对其进行编码。(). 存在添加节点、边和权重的简单函数。另外,绘制节点和边也很容易。谢谢,但我不想使用任何库