使用邻接列表实现图表表示时使用的数据结构

时间:2017-02-04 09:22:47

标签: python data-structures graph adjacency-list

我有一个非常大的关于1,000,000个节点和许多边缘的图表。这是我想知道哪个是实现邻接列表时最适合的数据结构。以下是我跟踪的对象

  • 边缘列表
  • 节点到节点连接列表

我正在使用python进行编码所以我使用了一个集合(因为根据this它具有ao(1)平均插入时间)用于边缘列表和字典到节点到节点的连接列表(通过使其完全可以清除)根据{{​​3}})。这是我的代码

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()

但是这段代码运行得非常慢,我可以加快速度吗?如果是这样,使用什么数据结构?

1 个答案:

答案 0 :(得分:0)

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

假设你有这样的输入:

4 4
1 2
3 2
4 3
1 4

第一行包含2个数字VE,下一个E行定义了两个顶点之间的边。

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

input = sys.stdin.read()
data = list(map(int, input.split()))
n, m = data[0:2]
data = data[2:]
edges = list(zip(data[0:(2 * m):2], data[1:(2 * m):2]))
x, y = data[2 * m:]
adj = [[] for _ in range(n)]
x, y = x - 1, y - 1
for (a, b) in edges:
    adj[a - 1].append(b - 1)
    adj[b - 1].append(a - 1)

让我们输出邻接列表adj

>>> print(adj)
[[1, 3], [0, 2], [1, 3], [2, 0]]

adj[0]有两个调整节点:1和3.意味着节点1有两个调整节点:2和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)

您将权重存储在cost中,例如,cost[0][1] = 3,cost[0][3] = 2。

希望这有帮助!