Commit 9c94737d authored by Martin Mareš's avatar Martin Mareš
Browse files

Grafy: Příklady na BFS a abstraktní reprezentaci grafu

parent 3c3f4938
#!/usr/bin/python3
# Abstraktní reprezentace grafu třídou,
# implementace třídy pomocí matice sousednosti
from collections import deque
class Graf:
"""Reprezentace grafu maticí sousednosti."""
def __init__(self, n):
self.n = n
self.matice = [[0]*n for _ in range(n)]
def __repr__(self):
return str(self.matice)
def pridej_hranu(self, i, j):
self.matice[i][j] = 1
# Na cyklus přes všechny vrcholy tentokrát potřebujeme vyrobit
# iterátor. Pozor, nestačí definovat metodu __iter__, protože
# potřebujeme předat jako parametr vrchol, jehož sousedy chceme
# vyjmenovat.
def sousede(self, i):
return SousedeIt(self, i)
class SousedeIt:
"""Iterátor přes sousedy zadaného vrcholu."""
def __init__(self, graf, i):
# Iterátor si pamatuje:
self.graf = graf # ke kterému grafu patří
self.i = i # sousedy kterého vrcholu vyjmenovává
self.j = 0 # aktuální polohu
# Pozor: Pokud napíšeme "for v in graf.sousede(u)", cyklus for bude chtít
# po objektu vráceném z metody sousede, aby vyrobil svůj iterátor. Jenže
# v našem případě to už iterátor je, tak ho musíme naučit, aby vrátil sám
# sebe. To je v Pythonu standardní postup: když iterátoru řeknete, že má
# vyrobit iterátor, vrátí sebe sama.
def __iter__(self):
return self
# Vrátí dalšího souseda v pořadí
def __next__(self):
# Kde je další jednička v řádku?
while self.j < self.graf.n and self.graf.matice[self.i][self.j] == 0:
self.j += 1
if self.j < self.graf.n:
self.j += 1
return self.j - 1
else:
raise StopIteration
# Původní příklad na prohledávání do šířky jsme přepsali tak,
# aby s grafem pracoval výhradně pomocí třídy Graf.
n = int(input())
graf = Graf(n)
for i in range(n):
for j in input().split():
graf.pridej_hranu(i, int(j))
print(graf)
def prohledej(v0):
byl_jsem = [False] * n
byl_jsem[v0] = True
vzdalenost = [None] * n
vzdalenost[v0] = 0
fronta = deque()
fronta.append(v0)
while fronta:
u = fronta.popleft()
print(u, vzdalenost[u])
for v in graf.sousede(u):
if not byl_jsem[v]:
byl_jsem[v] = True
vzdalenost[v] = vzdalenost[u] + 1
fronta.append(v)
prohledej(3)
#!/usr/bin/python3
# Abstraktní reprezentace grafu třídou,
# implementace třídy pomocí seznamů sousedů.
from collections import deque
class Graf:
"""Reprezentace grafu seznamy sousedů."""
def __init__(self, n):
self.n = n
self.seznam_sousedu = [[] for _ in range(n)]
def __repr__(self):
return str(self.seznam_sousedu)
def pridej_hranu(self, i, j):
self.seznam_sousedu[i].append(j)
# Používáme jako "for v in graf.sousede(u)"
def sousede(self, i):
return self.seznam_sousedu[i]
# Původní příklad na prohledávání do šířky jsme přepsali tak,
# aby s grafem pracoval výhradně pomocí třídy Graf.
n = int(input())
graf = Graf(n)
for i in range(n):
for j in input().split():
graf.pridej_hranu(i, int(j))
print(graf)
def prohledej(v0):
byl_jsem = [False] * n
byl_jsem[v0] = True
vzdalenost = [None] * n
vzdalenost[v0] = 0
fronta = deque()
fronta.append(v0)
while fronta:
u = fronta.popleft()
print(u, vzdalenost[u])
for v in graf.sousede(u):
if not byl_jsem[v]:
byl_jsem[v] = True
vzdalenost[v] = vzdalenost[u] + 1
fronta.append(v)
prohledej(3)
#!/usr/bin/python3
# Prohledávání grafu do šířky
# Graf je reprezentovaný pomocí matice sousednosti
from pprint import pprint
from collections import deque
# Načteme vstup: nejprve počet vrcholů, pak n řádků se sousedy jednotlivých vrcholů
n = int(input())
matice = [[0]*n for _ in range(n)]
for i in range(n):
for j in input().split():
j = int(j)
matice[i][j] = 1
# Pro kontrolu vypíšeme reprezentaci grafu (pprint = pretty print)
pprint(matice)
# Prohledávání do šířky
def prohledej(v0):
byl_jsem = [False] * n
byl_jsem[v0] = True
vzdalenost = [None] * n
vzdalenost[v0] = 0
fronta = deque()
fronta.append(v0)
while fronta:
u = fronta.popleft()
print(u, vzdalenost[u])
for v in range(n):
if matice[u][v] == 1 and not byl_jsem[v]:
byl_jsem[v] = True
vzdalenost[v] = vzdalenost[u] + 1
fronta.append(v)
prohledej(3)
#!/usr/bin/python3
# Prohledávání grafu do šířky
# Graf je reprezentovaný pomocí seznamů sousedů
from collections import deque
# Načteme vstup: nejprve počet vrcholů, pak n řádků se sousedy jednotlivých vrcholů
n = int(input())
sousede = []
for i in range(n):
sousede.append([ int(j) for j in input().split() ])
# Pro kontrolu vypíšeme reprezentaci grafu
print(sousede)
# Prohledávání do šířky
def prohledej(v0):
byl_jsem = [False] * n
byl_jsem[v0] = True
vzdalenost = [None] * n
vzdalenost[v0] = 0
fronta = deque()
fronta.append(v0)
while fronta:
u = fronta.popleft()
print(u, vzdalenost[u])
for v in sousede[u]:
if not byl_jsem[v]:
byl_jsem[v] = True
vzdalenost[v] = vzdalenost[u] + 1
fronta.append(v)
prohledej(3)
#!/usr/bin/python3
# Příklad na iterátory: vlastní implementace range(n)
class MyRange:
def __init__(self, n):
self.n = n
# Touto magickou metodou objektu řekneme, aby vyrobil iterátor
def __iter__(self):
return MyIter(self)
class MyIter:
# Iterátoru při inicializaci říkáme, ke kterému MyRange patří
def __init__(self, rng):
# Iterátor si pamatuje range a poslední vygenerované číslo
self.rng = rng
self.i = -1
# Touto magickou metodou po iterátoru chceme, aby vydal další prvek,
# nebo vyvolal výjimku StopIteration, pokud už žádný další neexistuje.
def __next__(self):
self.i += 1
if self.i < self.rng.n:
return self.i
else:
raise StopIteration
for x in MyRange(10):
print(x)
# Uvnitř for-u se stane toto:
#
# r = MyRange(10)
# it = r.__iter__() <- řekneme objektu MyRange, aby vyrobil iterátor
# while True:
# x = it.__next__() <- řekneme iterátoru, aby vydal další prvek
# pokud nastala výjimka StopIteration, skonči
# print(x) <- tělo cyklu
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment