유니티 자료구조

PTK·2025년 2월 19일
0

자료구조의 분류는 크게 2가지로, 선형 구조(Linear)비선형 구조(NonLinear)가 있다.

선형 구조(Linear)

선형 구조는 자료를 구성하는 원소들을 하나씩 순차적으로 나열시킨 형태이다.

자료들간의 앞, 뒤 관계가 1:1의 관계로 배열과 리스트가 대표적이며 스택과 큐도 이에 해당한다.

비선형 구조(NonLinear)

비선형 구조는 하나의 자료 뒤에 여러개의 자료가 존재할 수 있는 형태이다.

자료들간의 앞, 뒤 관계가 1:n또는 n:n의 관계를 나타낸다.

트리와 그래프가 대표적이며, 계층적 구조를 나타내기에 적절하다.

이미지 정리

Unity는 C#을 기반으로 하므로, C#의 기본 자료구조를 사용할 수 있다. 하지만 Unity에는 성능 최적화 및 게임 개발에 적합한 전용 자료구조도 존재한다.

1. 배열 (Array)

크기가 고정된 연속된 메모리 공간을 가지며, 빠른 인덱스 접근이 가능하지만 크기 변경이 불가능함.

int[] numbers = { 1, 2, 3, 4, 5 };
Console.WriteLine(numbers[0]); // 출력: 1

2. 리스트 (List)

크기가 동적으로 변할 수 있으며, 데이터를 추가/삭제할 수 있는 유연한 컬렉션 자료구조.

using System.Collections.Generic;

List<int> list = new List<int> { 1, 2, 3 };
list.Add(4);
Console.WriteLine(list[2]); // 출력: 3

3. 딕셔너리 (Dictionary<TKey, TValue>)

키-값 쌍으로 데이터를 저장하며, 키를 이용해 빠르게 값을 검색할 수 있는 자료구조.

using System.Collections.Generic;

Dictionary<string, int> scores = new Dictionary<string, int>();
scores["Alice"] = 100;
scores["Bob"] = 90;
Console.WriteLine(scores["Alice"]); // 출력: 100

4. 큐 (Queue)

선입선출(FIFO, First-In-First-Out) 방식으로 데이터를 저장하고 처리하는 자료구조.

using System.Collections.Generic;

Queue<int> queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);
Console.WriteLine(queue.Dequeue()); // 출력: 1

5. 스택 (Stack)

후입선출(LIFO, Last-In-First-Out) 방식으로 데이터를 저장하고 처리하는 자료구조.

using System.Collections.Generic;

Stack<int> stack = new Stack<int>();
stack.Push(10);
stack.Push(20);
Console.WriteLine(stack.Pop()); // 출력: 20

6. 해시셋 (HashSet)

중복을 허용하지 않으며, 빠른 검색과 삽입이 가능한 집합(Set) 자료구조.

using System.Collections.Generic;

HashSet<int> set = new HashSet<int> { 1, 2, 3 };
set.Add(2); // 중복 값 추가 안됨
Console.WriteLine(set.Contains(3)); // 출력: True

추가)

Array와 List의 차이점

크기가 고정되었다면 Array, 가변적이라면 List를 사용

추가)

해시테이블(HashTable)

딕셔너리(Dictionary)와 매우 유사하지만, 몇 가지 중요한 차이점이 있다.

해시테이블은 비제네릭(Non-generic) 컬렉션이므로, object 타입으로 값을 저장한다.
→ 값 타입(int, float 등)을 저장하면 박싱(Boxing)과 언박싱(Unboxing) 비용이 발생하여 성능이 떨어질 수 있다.

딕셔너리는 제네릭을 사용하므로 박싱/언박싱이 발생하지 않아 성능이 더 좋다.

추가)

연결 리스트(Linked List)

연결 리스트는 각 요소(Node)가 다음 요소를 가리키는 참조(포인터) 를 가지고 있는 선형 자료구조이다. 다른 선형 자료구조(배열, 리스트, 스택, 큐)등 중간에 삽입을 할 경우 최악의 경우 O(N)의 시간 복잡도를 가지지만 연결 리스트는 참조(포인터)를 가지고 있어 O(1)의 시간 복잡도로 삽입이 가능하다.

단점으로는 메모리 사용량이 배열보다 크고 임의의 위치에 있는 요소에 접근하라면 O(N)의 시간이 소요된다. (인덱스 접급이 불가능해서 순차적으로 읽어야하기 때문)

추가)

Call by Value, Call by Reference

1. Call by Value (값에 의한 호출)

변수를 함수에 전달하면, 그 변수의 "값"만 복사되어 전달된다.
함수 안에서 값을 변경해도 원래 변수에는 영향을 주지 않는다.
흔히 int, float, bool 같은 기본 데이터 타입에서 사용된다.

비유적으로 설명하면: "복사본을 가져가서 사용한다."

예를 들어, A가 B에게 문서 사본(복사본) 을 줬다고 가정해본다.
B가 사본을 수정해도 A가 가진 원본 문서는 변하지 않는다.

void ModifyValue(int num)
{
    num = 10;  // num의 값을 변경하지만, 원본 변수에는 영향을 주지 않음
}

void Start()
{
    int myValue = 5;
    ModifyValue(myValue);
    Debug.Log(myValue);  // 출력: 5 (원본 값 유지)
}

2. Call by Reference (참조에 의한 호출)

변수를 함수에 전달하면, 그 변수의 "메모리 주소"가 전달된다.
함수 안에서 값을 변경하면, 원래 변수도 변경된다.
ref, out 키워드를 사용하거나, class, List 같은 참조형 데이터 타입에서 사용된다.

비유적으로 설명하면: "원본을 직접 가져가서 사용한다."

이번에는 A가 B에게 원본 문서를 직접 건네줬다고 가정해본다.
B가 문서를 수정하면 A가 가진 문서도 똑같이 수정된다.

void ModifyRefValue(ref int num)
{
    num = 10;  // 원본 변수의 값을 변경
}

void Start()
{
    int myValue = 5;
    ModifyRefValue(ref myValue);
    Debug.Log(myValue);  // 출력: 10 (원본 값 변경됨)
}

0개의 댓글