C#에서 사용되는 대표적인 **자료구조(Data Structure)**에는 배열, 리스트, 스택, 큐, 딕셔너리, 해시셋 등이 있습니다. 각각의 자료구조는 특정한 상황에서 더 적합하게 사용할 수 있도록 설계되어 있습니다.
C# 기본 자료구조 개요
자료구조 | 설명 |
배열(Array) | 고정 크기의 연속된 메모리 블록 |
리스트(List) | 동적 크기 조절 가능, 배열과 유사 |
스택(Stack) | 후입선출(LIFO) 방식 |
큐(Queue) | 선입선출(FIFO) 방식 |
딕셔너리(Dictionary<TKey, TValue>) | 키-값 쌍 저장, 빠른 조회 |
해시셋(HashSet) | 중복 없는 유일한 값 저장 |
링크드 리스트(LinkedList) | 노드 기반의 동적 자료구조 |
정렬된 리스트(SortedList<TKey, TValue>) | 키를 기준으로 자동 정렬되는 리스트 |
배열(Array)
1. 특징
- 고정된 크기를 가지며, 연속된 메모리 공간을 차지
- 빠른 인덱스 접근 가능 (O(1))
- 크기 변경 불가능
2. 사용 예시
int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
Console.WriteLine(numbers[2]); // 출력: 3
리스트(List)
1. 특징
- 배열과 유사하지만 동적 크기 조절 가능
- 내부적으로 배열을 사용하지만, 크기 초과 시 자동으로 새로운 배열을 할당
- 삽입/삭제가 용이
2. 사용 예시
List<int> list = new List<int> { 1, 2, 3 };
list.Add(4);
list.Remove(2);
Console.WriteLine(list.Count); // 출력: 3
스택(Stack)
1. 특징
- 후입선출(LIFO, Last In First Out) 구조
- Push()로 삽입, Pop()으로 제거
2. 사용 예시
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
stack.Push(3);
Console.WriteLine(stack.Pop()); // 출력: 3
Console.WriteLine(stack.Peek()); // 출력: 2 (삭제 안 됨)
큐(Queue)
1. 특징
- 선입선출(FIFO, First In First Out) 구조
- Enqueue()로 삽입, Dequeue()로 제거
2. 사용 예시
Queue<int> queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
Console.WriteLine(queue.Dequeue()); // 출력: 1
Console.WriteLine(queue.Peek()); // 출력: 2 (삭제 안 됨)
딕셔너리(Dictionary<TKey, TValue>)
1. 특징
- 키-값(Key-Value) 쌍으로 데이터 저장
- 특정 키를 빠르게 조회 가능 (해시 기반 O(1))
2. 사용 예시
Dictionary<string, int> ages = new Dictionary<string, int>();
ages["Alice"] = 25;
ages["Bob"] = 30;
Console.WriteLine(ages["Alice"]); // 출력: 25
해시셋(HashSet)
1. 특징
- 중복 없는 값 저장
- 검색 및 삽입 속도가 빠름 (해시 기반 O(1))
2. 사용 예시
HashSet<int> set = new HashSet<int> { 1, 2, 3 };
set.Add(3); // 추가되지 않음 (중복 허용 안 함)
Console.WriteLine(set.Contains(2)); // 출력: True
링크드 리스트(LinkedList)
1. 특징
- 동적으로 크기가 조절 가능
- 노드 기반의 자료구조로, 삽입/삭제가 빠름 (O(1)~O(n))
- 단일 연결 리스트 및 이중 연결 리스트 존재
2. 사용 예시
LinkedList<int> linkedList = new LinkedList<int>();
linkedList.AddLast(1);
linkedList.AddLast(2);
linkedList.AddFirst(0);
Console.WriteLine(linkedList.First.Value); // 출력: 0
정렬된 리스트(SortedList<TKey, TValue>)
1. 특징
- 키를 기준으로 자동 정렬되는 리스트
- Dictionary와 유사하지만 키가 정렬된 상태로 유지됨
2. 사용 예시
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.Add(2, "B");
sortedList.Add(1, "A");
sortedList.Add(3, "C");
Console.WriteLine(sortedList[1]); // 출력: A
우선순위 큐(PriorityQueue<TPriority, TValue>)
1. 특징
- 우선순위가 높은 요소를 먼저 처리하는 큐
- 일반적인 큐와 달리 요소가 삽입될 때 우선순위에 따라 정렬됨
- Enqueue()로 삽입, Dequeue()로 가장 높은 우선순위 요소 제거
2. 사용 예시
PriorityQueue<string, int> priorityQueue = new PriorityQueue<string, int>();
priorityQueue.Enqueue("Low Priority", 3);
priorityQueue.Enqueue("High Priority", 1);
priorityQueue.Enqueue("Medium Priority", 2);
Console.WriteLine(priorityQueue.Dequeue()); // 출력: High Priority
Q&A
Q: C#에서 리스트와 배열의 차이점은 무엇인가요?
A: 배열은 크기가 고정되어 변경할 수 없지만, 리스트는 동적으로 크기가 조절됩니다. 리스트는 내부적으로 배열을 사용하지만 크기를 자동 조절할 수 있어 유연성이 더 높습니다.
Q: 스택과 큐의 차이점은 무엇인가요?
A: 스택은 후입선출(LIFO) 방식으로 작동하며, 큐는 선입선출(FIFO) 방식으로 작동합니다. 즉, 스택에서는 마지막에 추가된 요소가 먼저 제거되고, 큐에서는 가장 먼저 추가된 요소가 먼저 제거됩니다.
Q: 딕셔너리와 해시셋의 차이점은 무엇인가요?
A: 딕셔너리는 키-값(Key-Value) 쌍을 저장하는 반면, 해시셋은 단순한 값(Value)만 저장합니다. 또한, 딕셔너리는 특정 키를 통해 값을 조회할 수 있으며, 해시셋은 중복을 허용하지 않는다는 차이가 있습니다.
Q: 링크드 리스트와 배열의 차이점은 무엇인가요?
A: 배열은 연속된 메모리 공간을 차지하지만, 링크드 리스트는 노드로 구성되어 있어 비연속적인 메모리를 사용할 수 있습니다. 배열은 인덱스를 통한 빠른 접근이 가능하지만 크기가 고정적이며, 링크드 리스트는 동적으로 크기가 조절되지만 노드 탐색 시 O(n)의 시간이 걸릴 수 있습니다.
Q: 정렬된 리스트(SortedList)와 딕셔너리(Dictionary)의 차이점은 무엇인가요?
A: SortedList<TKey, TValue>는 키를 자동 정렬하지만, Dictionary<TKey, TValue>는 입력 순서대로 저장됩니다. SortedList는 정렬된 데이터를 다룰 때 유리하지만 삽입 및 삭제 성능은 Dictionary보다 느릴 수 있습니다.
결론
C#에서는 다양한 자료구조가 제공되며, 각각의 특징과 성능을 이해하고 적절한 상황에서 활용하는 것이 중요합니다.
- 빠른 접근이 필요하면? 👉 배열, 딕셔너리
- 동적 크기 조절이 필요하면? 👉 리스트, 링크드 리스트
- 선입선출(FIFO)이 필요하면? 👉 큐
- 후입선출(LIFO)이 필요하면? 👉 스택
- 중복 없는 데이터가 필요하면? 👉 해시셋
- 키-값 매핑이 필요하면? 👉 딕셔너리, 정렬된 리스트
- 우선순위 처리가 필요하면? 👉 우선순위 큐
적절한 자료구조를 선택하면 성능을 최적화할 수 있으며, 코드의 효율성을 높일 수 있습니다. 🚀