[Unity] 유니티(C#) 자료구조 - Queue, Stack

조재훈·2024년 6월 27일

Queue

흔히 FIFO로 알고있는 큐를 유니티에서 알아보자

유니티에서는 제네릭으로 타입을 지정하는 Queue<T>로 타입을 지정하는데 System.Collections.Generic 네임스페이스에 포함되어 있다

FIFO는 쉽게 말해 먼저 들어간 데이터가 가장 먼저 나온다는 것을 의미한다(like 웨이팅)

내가 진행중인 프로젝트에서는 턴제 게임에서 전투에 참여하는 캐릭터들을 Queue에 담아 다음 턴의 캐릭터 순서대로 나온다

배열과 리스트에서는 데이터를 추가하거나 참조할 때 특정 인덱스로 자료구조 중간에 있는 데이터도 볼 수 있지만 큐와 뒤에 나올 스택은 그렇지 못함

C#에서 큐는 내부적으로 배열을 사용해 요소를 저장하고 배열의 크기가 부족해질때 새로 할당해 요소를 복사하는 식임 -> 컴공 다니면서 한 번쯤 자료구조를 구현해봤으면 알 내용?

  • 큐의 활용 사례로는
    • 이벤트 처리 : 순차적으로 발생하는 이벤트들을 큐에 담아 처리할 때 좋음(ex. 네트워크 메시지 처리)
    • 작업 큐 : 비동기작업들을 큐에 담아두고 순차적으로 처리할 때 쓰면 좋음
    • 경로 찾기 : BFS에서 큐를 사용해 그래프를 탐색할 수 있음

선언 및 초기화

큐를 선언하는 방법

public Queue<int> intQueue;

다음과 같이 타입을 지정하고 선언할 수 있다. 그런데 배열이나 리스트는 public이나 직렬화를 했을 때 알아서 초기화돼서 null 참조가 안되지만 큐는 직렬화를 지원안해서 따로 직렬화를 시켜줘야 한다

큐 초기화

// 기본적으로는 
intQueue = new Queue<int>();

// 초기 용량을 설정하려면? 
intQueue = new Queue<int>(10);

// 컬렉션(배열, 리스트)으로 초기화도 가능하다
int[] intArray = new int[] {1, 2, 3, 4};
intQueue = new Queue<int>(intArray);

큐 함수

Enqueue

큐에 데이터를 추가하는 함수. 큐의 맨 끝에 데이터가 추가된다

intQueue.EnQueue(10);
// 1 2 3 4 10

Dequeue

큐에 데이터를 제거하는 함수. 큐의 맨 처음 데이터가 제거된다

intQueue.Dequeue();
// 2 3 4

Peek

큐의 맨 앞 데이터를 빼지 않고 보기만 하는 함수. 큐가 비어있을 때 사용하면 에러가 나므로 주의
해당 타입의 데이터를 반환한다

Debug.Log(intQueue.Peek());

// 1

Clear

큐의 모든 요소들을 제거한다

intQueue.Clear();

// 

Contains

큐에 매개변수로 넘겨준 데이터와 일치하는 데이터가 있는지 확인해 bool 값을 반환한다

intQueue.Contains(1);

// true

큐도 Contains 함수가 있는지 몰랐는데 그냥 큐에서 데이터를 빼고 다시 넣으면서 있는지 확인하는 줄 알았는데 그냥 큐의 내부 배열을 순회한다고 한다

ToArray

큐를 배열로 변환하는 함수. 리스트로 바꿀려면 배열로 바꿨다가 리스트로 바꾸는 것 같다

int[] intArray = intQueue.ToArray();

// 1 2 3

Stack

이번엔 LIFO로 알려진 스택이다

유니티에서는 제네릭으로 타입을 지정하는 Stack<T>로 타입을 지정하는데 System.Collections.Generic 네임스페이스에 포함되어 있다

가장 나중에 들어간 데이터가 가장 먼저 빠져나온다라는 개념

큐와 구현은 거의 비슷함

선언과 초기화

선언

public Stack<int> intStack;

초기화

// 기본 초기화
intStack = new Stack<int>();

// 초기 용량 미리 지정
intStack = new Stack<int>(10);

// 컬렉션 미리 지정
intStack = new Stack<int>(intArray);

위에서 컬렉션으로 스택을 초기화할 때 컬렉션의 뒤에 있는 데이터가 스택에서 젤 먼저 꺼내진다

while(intStack.Count > 0)
{
	Debug.Log(intStack.Pop());
}

// 3 2 1

스택 함수

스택 함수는 거의 큐와 비슷한데 그냥 데이터를 추가하고 제거하는 함수만 다르다고 봐도 무방함

Push

스택의 맨 위에 데이터를 추가하는 함수

intStack.Push(10);

// 1 2 3 10

Pop

스택의 맨 위에 있는 데이터를 제거하는 함수. 데이터 타입에 맞는 타입을 반환

intStack.Pop();

// 3

큐와 스택

큐와 스택은 배열, 리스트와 달리 인덱스를 통한 접근을 허용하지 않고 배열, 리스트로는 큐와 스택을 흉내낼 수 있지만 큐와 스택은 배열, 리스트를 흉내낼 수 없다

이렇게 기능을 제한했으면 무언가 얻는 것이 있지 않을까?? 그렇다. 원소의 삽입과 제거가 빈번하게 일어나는 자료구조의 경우 리스트보다 큐 및 스택으로 구현하는 것이 좋다

profile
나태지옥

0개의 댓글