deck:: Logseq/coding tip

- ## 1. 개념(Concept)
	- 분리집합(Disjoint Set)이란, 서로 공통된 원소를 가지고 있지 않은 {{cloze **상호 배타적인 집합(Disjoint Set)**}}들을 관리하는 자료구조.
	  id:: 694400bf-c237-4938-945f-26e4e646edbe
	- 핵심 연산
		- Union (합치기): 두 원소가 속한 집합을 하나로 합침.
		- Find (찾기): 특정 원소가 속한 집합의 대표자(Root)를 찾음. 이를 통해 두 원소가 같은 집합에 있는지 확인 할 수 있음.
- ## 2. 기본 구조 (Basic Structure)
	- 일반적으로 {{cloze **트리구조**}} 를 사용하여 구현하며, 배열( parent[] )로 각 원소의 부모 노드를 저장.
	  id:: 69440256-0454-4ca4-a92a-71f8cfe6a7d6
	- **초기화**
		- {{cloze 모든 원소가 자기 자신을 부모로 가리키며, 각각이 하나의 독립된 집합으로 초기화( parent[i] = i ) :: 초기화 방법을 서술할 것}} 
		  extra:: 즉 자기 자신을 root로 가지는 배열로 parent 배열을 초기화 함.
		  id:: 69440216-6ce1-4ac5-a14b-f014bf8f9a85
	- **Find 연산**
		- 원소의 부모를 타고 올라가며 루트 노드(자기 자신이 부모인 노드)를 찾음.
		- **경로 압축 (Path Compression) - Find 최적화**
			- Find  연산을 수행할 때, 루트 노드를 찾으면서 거쳐간 모든 노드의 부모를 루트 노드로 바로 갱신해버리는 기법.
			- 효과 : 다음에 해당 노드들을 탐색할 때 루트까지 바로 갈 수 있어 트리의 높이가 획기적으로 낮아짐.
			- **구현**
				- id:: 69440457-ee29-4b06-9a75-9e6c3debd508
				  replacecloze:: " '      	parent[x] = find(parent[x])' "
				  ```python
				  def find(x) :
				    	if parent[x] != x :
				        	parent[x] = find(parent[x])
				      return parent[x]
				  ```
	- **Union 연산**
		- 두 원소의 루트 노드를 찾은 뒤( Find ), 한쪽 루트의 부모를 다른 쪽 루트로 설정하여 트리를 연결
		- **랭크 기반 합치기 (Union by Rank) - Union 최적화**
			- Union  연산을 할 때, 무조건 합치는 것이 아니라 트리의 높이(Rank)가 낮은 트리를 높은 트리 밑에 붙이는 기법
			- 효과 : 트리의 전체 높이가 불필요하게 커지는 것을 방지하여 밸런스를 유지
			- **구현** #card
			  id:: 69440755-56a2-43b9-9bfc-a3fc5a7ae098
			  #+BEGIN_EXTRA
			  초기화 시 parent 배열과 같은 길이의 rank 배열이 선언되어 있고 0으로 초기화 되어 있음(1로 초기화 해도 됨. 어차피 상대적인 높이 대소비교만 가능하면 어떤 숫자로 초기화 해도 상관 없음. 보통 root의 깊이를 0으로 보고 0으로 초기화 하거나, 트리의 길이를 의미하도록 하기 위해서 시작을 1로 초기화 하는 경우도 있음.
			  #+END_EXTRA
				- ```python
				  def union(x, y) :
				    	x = find(x)
				      y = find(y)
				      
				      if x == y :
				        	return
				      
				      if rank[x] < rank[y] :
				        	x, y = y, x # x의 랭크가 더 크거나 같도록 스왑
				          
				      parent[y] = x
				      if rank[x] == rank[y] :
				        	rank[x] += 1
				  ```
- ## 3. 시간 복잡도
  (어떤 경우던 Find 연산이 포함되어 있기에 Find 연산 기준으로 설명)
	- ### 1) 최적화 적용이 없을 경우
		- (어떤 경우던 Find 연산이 포함되어 있기에 Find 연산 기준으로 설명)
		- 최적화가 없을 경우 루트를 찾기 위해 자식부터 위로 쭉 올라가서 부모를 찾음. 따라서 마치 연결리스트 마냥 전체를 쭉 순회해야하기에 시간 복잡도는 {{cloze **O(N)**}}
		  id:: 6944e937-52e3-47af-b628-397a1c5b1d28
	- ### 2) 최적화 적용 시(경로 압축 + 랭크 기반 합치기)
		- 시간 복잡도는 {{cloze **O(α(n))**}} #card
		  id:: 6944e9fb-f794-424c-beed-d75da1a90821
		  #+BEGIN_EXTRA
		  경로 압축과 랭크 높이를 제어함으로서 최종적으로 역 아커만 함수 α(n)에 비례하는 시간복잡도를 가짐.
		  역 아커만 함수는 매우 느리게 증가하는 함수로서 이때문에 현실적인 경우에는 시간복잡도가 **O(1)**과 거의 같아짐. 즉 분리집합에서 find 연산이 상수 시간 복잡도를 이용하는 것과 거의 같아지게 됨.
		  #+END_EXTRA
		-
- ## 4. 사용 예시
	- 분리집합은 {{cloze “그룹핑”이나 “연결성 확인” :: 2개의 경우를 답할 것}} 이 필요한 문제에서 주로 사용됨. (사용 예시 4가지)#card #depth-1
	  id:: 69440b31-d327-4c9d-b81f-511b696dd893
		- 그래프의 사이클 판별
			- 무방향 그래프에서 간선을 추가할 때, {{cloze **두 노드의 루트가 이미 같다면(이미 연결되어 있다면)** :: 확인 방법을 서술할 것}}  사이클이 발생한 것.
			  id:: 69440b31-14b8-4edf-83b5-c514e1b0362e
		- [[크루스칼 알고리즘(Kruskal’s Algorithm)]]
			- {{cloze 최소 신장 트리(Minimum Spanning Tree)}} 를 구할 때, 간선을 가중치 순으로 선택하면서 사이클이 생기지 않도록 집합을 합치는 데 사용
			  id:: 69440b31-b3ea-4010-a500-eb486372ed1a
		- 네트워크 연결 확인 : 컴퓨터 네트워크, 친구 관계 등 연결된 그룹의 개수나 크기를 구할 때 사용.
		- 이미지 분할 : 픽셀들을 영역별로 그룹화할 때 응용