Graphs and Union-Find
Graphs
We worked with trees before. A tree is a special kind of graph, with extra restrictions (trees can't have cycles).
Graphs are useful. Let's write a graph for a social network:
class Person:
def __init__(self, person_id: str):
self.id = person_id
self.friends: set[Person] = set()
def __str__(self) -> str:
return self.id
def __repr__(self) -> str:
return self.__str__()
class SocialGraph:
def __init__(self, location: str) -> None:
self.people: set[Person] = set()
self.location = location
def __str__(self) -> str:
return f'People in {self.location}: {self.people}'
students = SocialGraph('Oakland')
me = Person('Rasika')
students.people.add(me)
mini = Person('Mini')
students.people.add(mini)
me.friends.add(mini)
mini.friends.add(me)
print(students) # People in Oakland: {Mini, Rasika}
famous_person = Person('Famous')
students.people.add(famous_person)
me.friends.add(famous_person)
mini.friends.add(famous_person)
print(me.friends) # {Mini, Famous}
print(mini.friends) # {Rasika, Famous}
print(famous_person.friends) # set()
Terminology:
- Directed: the edges point from one node, to another
- Undirected: the edges do not have a specific direction; all edges go both ways
Poll: Is our social media graph above directed or undirected?
- Directed
- Undirected
Union-Find
Union Find slides: https://github.com/neu-pdi/cs2100-public-resources/blob/main/static/pdfs/26sp/union-find.pdf (Polls below)
Poll: How might we implement find(node)?
- As long as node has no children, re-point the node variable to its parent. When node has children, return it
- As long as node is not its own parent, re-point the node variable to its parent. When node is its own parent, return it
- If node is its own parent, return the node. Otherwise, return find(node.parent)
- If node's parent is null, return the node. Otherwise, return find(node.parent)
Poll: How might we implement union(node1, node2)?
- Find both nodes' roots. If the two roots are different, then make one of the roots the other root's parent
- Find both nodes' roots. If the two roots are the same, then do nothing
- If the two nodes have different parents, then make one of the nodes the other node's parent
- If the two nodes have the same parent, then make one of the nodes the other node's parent
Poll: Why do we check if root1.rank == root2.rank before incrementing root2.rank?
- That's wrong - we should always increment root2.rank
- That's wrong - we should always increment both root1.rank and root2.rank
- If they have the same rank, then they have the same height in the tree. If root2 becomes root1's parent, then root2 is going higher up in the tree
- If they have the same rank, then they have the same number of children. If root2 becomes root1's parent, then root2 is getting another child
Poll: What does the Union-Find algorithm do?
- It groups nodes into sets such that none of the nodes in each set are connected to each other, and all of the edges are between two sets
- It groups nodes into sets such that the nodes in each set are connected to each other, and there are no edges between two sets
- It groups edges into sets such that none of the sets of edges have any nodes in common
- It works on undirected graphs (all edges go both ways)
- It works on directed graphs (all edges are one-way)