자료구조: 그래프 (Graph)
그래프는 노드(정점)들과 그들을 연결하는 간선들의 집합으로 이루어진 자료구조
트리와 달리 순환이 허용되며, 더 유연한 관계 표현이 가능.
그래프의 주요 특징:
- 방향성: 방향 그래프(Directed Graph)와 무방향 그래프(Undirected Graph)로 구분됨.
- 가중치: 간선에 비용이나 거리 등의 가중치를 부여할 수 있습니다.
- 순환성: 순환(Cycle)이 허용되어 한 노드에서 시작하여 같은 노드로 돌아올 수 있습니다.
- 연결성: 모든 노드가 연결되어 있지 않을 수 있습니다.
그래프의 구현 방법:
- 인접 행렬 (Adjacency Matrix): 2차원 배열을 사용하여 노드 간의 연결 관계를 표현합니다.
- 인접 리스트 (Adjacency List): 각 노드마다 연결된 노드들의 리스트를 유지합니다.

(295) EBS 링크 소프트웨어 세상, "가장 빠른길을 찾아라, 최단경로 알고리즘" - YouTube
AVL 트리
자동으로 균형을 맞추는 이진 탐색 트리로, 왼쪽과 오른쪽 서브트리의 높이 차이가 최대 1.

public int height;
// 이 노드의 높이를 나타내는 변수
트리의 균형을 맞추기 위해 AVL 트리에서는 각 노드의 높이를 계산해 놓음.
public Vector2 position;
// 이 노드의 화면상 위치를 나타내는 변수
Vector2는 두 개의 값(x, y)을 갖는 구조체로, 주로 2D 공간에서 위치를 지정할 때 사용됨.
this.height = 1;
// 노드가 생성될 때 height 값을 1로 초기화
private Node root;
// root는 트리의 최상위 노드를 참조. 이 변수는 트리의 시작점이자 첫 번째 노드로 사용
트리를 구현할 때, 루트 노드를 통해 모든 다른 노드들에 접근하거나 트리 구조를 변경할 수 있음.

Insert(i);
// Insert(i) 메서드를 호출(9번 반복후에 종료)
UpdatePositions(root, 0, 0, 2);
- 0, 0
// 트리의 초기 위치(예: 화면 좌표)를 나타내는 값
- 2
// 트리 노드들 간의 간격 또는 스케일 값을 나타냄
public void Insert(int data)
// 주어진 data 값을 이진 탐색 트리(BST)에 삽입하는 함수.
이 함수는 InsertRec 함수로 재귀적인 삽입 작업을 위임함.
root = InsertRec(root, data)
// InsertRec()는 트리 구조에서 데이터를 삽입하는 재귀 함수.
이 함수는 트리의 노드들을 하나씩 탐색하며 적절한 위치에 새로운 값을 삽입함.

if (node == null)
return new Node(data);
// 현재 노드가 null이면 새 노드를 삽입할 위치를 찾은 것
if (data < node.data)
node.left = InsertRec(node.left, data)
// 삽입하려는 값이 현재 노드의 값(node.data)보다 작으면
왼쪽 서브트리로 재귀 호출 하여, 왼쪽 서브트리로 할당.
else if (data > node.data)
node.right = InsertRec(node.right, data);
// 삽입하려는 값이 현재 노드의 값(node.data)보다 크다면
오른쪽 서브트리로 재귀 호출 하여, 오른쪽 서브트리로 할당.
else return node;
// 삽입하려는 값이 현재 노드의 값과 같으면 아무 것도 하지 않고 노드를 반환
UpdateHeight(node);
// 삽입 후 노드의 높이를 업데이트
return Balance(node, data);
// 트리의 균형을 맞추는 작업을 수행 (AVL 트리의 균형을 맞추는 함수)
return node == null ? 0 : node.height;
// 현재 노드가 null 이면, 0. null 이 아니면 node.height 를 반환.

return node == null ? 0 : Height(node.left) - Height(node.right);
// 현재 노드가 null 이면, 0.
null 이 아니면 왼쪽 서브트리의 높이에서 오른쪽 서브트리의 높이를 빼는 방식으로 계산.
if (node != null)
node.height = Mathf.Max(Height(node.left), Height(node.right)) + 1;
// node가 null 이 아니라면 하기의 코드를 실행
왼쪽 자식 노드와 오른쪽 자식 노드의 높이 중 더 큰 값을 찾음
(Mathf.Max(Height(node.left), Height(node.right)))
나온 값에 +1 을 실행하여, 현재 노드의 높이를 설정.
Node x = y.left;
Node T2 = x.right;
// y의 왼쪽 자식 노드를 x로 설정
// x의 오른쪽 자식 노드를 T2로 설정
x.right = y;
y.left = T2;
// x의 오른쪽 자식을 y로 설정
// y의 왼쪽 자식을 T2로 설정
UpdateHeight(y);
UpdateHeight(x);
// y의 높이 업데이트
// x의 높이 업데이트
return x;
// 새로운 루트인 x를 반환

Node y = x.right;
Node T2 = y.left;
// x의 오른쪽 자식 노드를 y로 설정
// y의 왼쪽 자식 노드를 T2로 설정
y.left = x;
x.right = T2;
// y의 왼쪽 자식을 x로 설정
// x의 오른쪽 자식을 T2로 설정
UpdateHeight(x);
UpdateHeight(y);
// x의 높이 업데이트
// y의 높이 업데이트
return y;
// 새로운 루트인 y를 반환
int balance = GetBalance(node);
// 노드의 균형 계수를 계산
if (balance > 1 && data < node.left.data)
return RightRotate(node);
// 왼쪽 자식이 불균형하고, 새로운 데이터가 현재 노드의 왼쪽 자식 노드보다 작을 때
// 오른쪽 회전 (Right Rotation)
if (balance < -1 && data > node.right.data)
return LeftRotate(node);
// 오른쪽 자식이 불균형하고, 새로운 데이터가 현재 노드의 오른쪽 자식 노드보다 작을 때
// 왼쪽 회전 (Left Rotation)
if (balance > 1 && data > node.left.data)
node.left = LeftRotate(node.left);
return RightRotate(node);
// 왼쪽 자식이 불균형하고, 새로운 데이터가 현재 노드의 왼쪽 자식 노드보다 작을 때
// 왼쪽 자식에 대해 왼쪽 회전
// 오른쪽 회전 (Right Rotation)
if (balance < -1 && data < node.right.data)
node.right = RightRotate(node.right);
return LeftRotate(node);
// 오른쪽 자식이 불균형하고, 새로운 데이터가 현재 노드의 오른쪽 자식 노드보다 작을 때
// 오른쪽 자식에 대해 오른쪽 회전
// 왼쪽 회전 (LeftRotate)
return node;
// 트리가 균형을 이룬 경우 노드를 그대로 반환

UpdatePositions(Node node, float x, float y, float horizontalSpacing)
// AVL 트리의 노드들에 대한 2D 좌표를 계산하여 각 노드의 position을 설정
트리의 구조를 화면에 그리기 위한 좌표 배치후
각 노드가 트리 구조에 맞게 적절한 위치에 배치되도록 x, y 좌표를 갱신
if (node == null) return
// node가 null이면 더 이상 진행할 필요가 없으므로 종료
node.position = new Vector2(x, y)
// 현재 노드의 position을 Vector2(x, y)로 설정하여 이 노드의 2D 좌표를 정의
UpdatePositions(node.left, x - horizontalSpacing, y - 1.5f, horizontalSpacing / 2)
// 현재 노드의 왼쪽 자식에 대해, 수평 좌표 x를 왼쪽으로 이동
수직 좌표 y를 아래로 내려가게 설정한 뒤
수평 간격을 절반으로 줄여서 왼쪽 자식의 위치를 설정
UpdatePositions(node.right, x + horizontalSpacing, y - 1.5f, horizontalSpacing / 2)
// 현재 노드의 오른쪽 자식에 대해, 수평 좌표 x를 오른쪽으로 이동
수직 좌표 y를 아래로 내려가게 설정한 뒤
수평 간격을 절반으로 줄여서 왼쪽 자식의 위치를 설정

OnDrawGizmos()
// Unity에서 Gizmos를 사용하여 게임 오브젝트를 시각화할 때 사용
이 함수 내부에서는 DrawNode(root)가 호출되며, 이를 통해 트리 구조를 그리게 됨.
if (root != null)
// 트리가 비어 있지 않으면, 트리의 루트 노드를 기준으로 그리기 시작.
DrawNode(root)
// 루트 노드를 그리기 위한 함수. 이 함수는 트리의 루트를 시작으로 각 노드를 시각적으로 표현할 수 있음.

Gizmos.color = Color.white
// 선의 색을 흰색으로 설정하고, Gizmos.DrawLine은 두 점을 연결하는 선을 그림
Gizmos.DrawLine(new Vector3(node.position.x, node.position.y, 0),
new Vector3(node.left.position.x, node.left.position.y, 0));
// 부모 노드(node.position)와 왼쪽 자식 노드(node.left.position) 간에 선을 그림
Gizmos.DrawLine(new Vector3(node.position.x, node.position.y, 0),
new Vector3(node.right.position.x, node.right.position.y, 0));
// 부모 노드(node.position)와 오른쪽 자식 노드(node.right.position) 간에 선을 그림
Gizmos.color = Color.cyan;
// 원의색(Sphere)을 cyan 으로 설정함
Gizmos.DrawSphere(new Vector3(node.position.x, node.position.y, 0), 0.2f);
// (node.position.x, node.position.y, 0) 위치에 반지름 0.2f 크기의 구체를 그림
UnityEditor.Handles.Label(new Vector3(node.position.x, node.position.y + 0.3f, 0),
$" {node.data} (h:{node.height})");
- UnityEditor.Handles.Label
// 노드의 데이터를 텍스트로 표시하는데 사용
- (node.position.x, node.position.y + 0.3f, 0)
// 노드의 위치는 상기의 코드 로, 원의 위쪽에 약간 오프셋을 주어 텍스트를 표시함.
- $" {node.data} (h:{node.height})");
// node.data는 노드의 데이터, node.height는 노드의 높이를 나타내며, 이 값들을 텍스트로 표시
DrawNode(node.left);
DrawNode(node.right);
// DrawNode(node.left)와 DrawNode(node.right)는 왼쪽 자식과 오른쪽 자식을 재귀적으로 그림
이로 인해 트리 구조의 모든 노드가 그려짐.
'게임 개발(유니티) > 멋쟁이 사자처럼 3기_회고록' 카테고리의 다른 글
| [멋쟁이사자처럼 유니티 TIL] 2024_12_12(목) 강의 요약 및 정리(1) (0) | 2024.12.12 |
|---|---|
| [멋쟁이사자처럼 유니티 TIL] 2024_12_11(수) 강의 요약 및 정리 (0) | 2024.12.11 |
| [멋쟁이사자처럼 유니티 TIL] 2024_12_10(화) 강의 요약 및 정리(1) (0) | 2024.12.10 |
| [멋쟁이사자처럼 유니티 TIL] 2024_12_06(금) 강의 요약 및 정리 (0) | 2024.12.08 |
| [멋쟁이사자처럼 유니티 TIL] 2024_12_05(목) 강의 요약 및 정리(2) (0) | 2024.12.08 |