C# - 배열과 컬렉션

MothorMoth·2024년 4월 24일

C#

목록 보기
7/17
post-thumbnail

배열

  • 동일한 데이터 타입의 요소들을 연속된 메모리에 저장하는 고정 크기의 데이터 구조

1. 1차원 배열

  • 선언된 크기 만큼의 공간을 메모리에 할당 받아 동일한 데이터 타입의 요소들을 저장하고 인덱스를 통해 접근할 수 있다.
// 배열 선언
int[] arr;

// 배열의 크기 지정
arr = new int[5];

// 배열 선언과 동시에 크기 지정
int[] arr = new int[5];

// 배열 요소에 값 할당
arr[0] = 1;

// 배열 요소에 접근
Console.WriteLine(arr[0]); // 출력 1

2. 다차원 배열

  • 여러 배열을 하나로 묶어 놓은 배열로, C#에서는 각 차원의 크기를 지정하여 생성하며, 2차원이상의 형태를 의미한다.
// 다차원 배열 선언
int[,] arr2D;

// 다차원 배열의 크기 지정
arr2D = new int[2, 3];

// 다차원 배열 선언과 동시에 크기 지정
int[,] arr2D = new int[2, 3];

// 다차원 배열 요소에 값 할당
arr2D[0, 0] = 1;

// 다차원 배열 요소에 접근
Console.WriteLine(arr2D[0, 0]); // 출력 1

// 3차원 배열의 선언과 초기화
int[,,] arr3D = new int[2, 3, 4] 
{
    { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } },
    { { 13, 14, 15, 16 }, { 17, 18, 19, 20 }, { 21, 22, 23, 24 } }
};

// 3차원 배열 요소에 접근
Console.WriteLine(arr3D[1, 2, 3]);  // 출력 24

컬렉션

  • 다양한 데이터 타입의 요소들을 유동적으로 관리할 수 있는 데이터 구조의 집합

1. List

  • 가변적인 크기를 가지고 있으며, 생성할 때 담을 자료형을 지정한다.
// 리스트 선언
List<int> numbers = new List<int>();

// 리스트에 데이터 추가
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);

// 리스트에서 데이터 삭제
numbers.Remove(2);

// 리스트 데이터 출력
foreach(int number in numbers)
{
    Console.WriteLine(number);
}

// 출력
// 1
// 3

리스트는 동적으로 크기를 조정할 수 있어 배열과는 다르게 유연한 데이터 구조를 구현할 수 있지만, 리스트를 무분별하게 사용하는 것은 좋지 않은 습관이다.

1. 메모리 사용량 증가: 리스트는 동적으로 크기를 조정할 수 있어 배열보다 많은 메모리를 사용할 수 있으며, 이로 인해 많은 데이터를 다루는 경우 무분별한 사용이 성능 저하를 초래할 수 있다.
2. 데이터 접근 시간 증가: 리스트는 연결 리스트로 구현되어 있어, 인덱스를 통한 데이터 접근이 배열보다 느리고, 특정 인덱스의 데이터를 찾기 위해 연결된 노드를 순회해야 하기 때문에 무분별한 사용은 데이터 접근 시간을 증가시켜 성능 저하를 초래할 수 있다.
3. 코드 복잡도 증가: 리스트는 동적으로 크기를 조정할 수 있어 데이터 추가나 삭제가 배열보다 간편하지만, 이 유연성이 코드 복잡도를 증가시키고, 적절한 데이터 처리를 요구하는 코드를 작성해야 하므로 코드의 가독성과 유지보수성이 저하될 수 있다.

2. Dictionary

  • 키와 값의 쌍으로 구성된 데이터 구조로, 중복된 키를 가질 수 없다.
// 딕셔너리 선언
Dictionary<string, int> scores = new Dictionary<string, int>();

// 딕셔너리에 데이터 추가
scores.Add("Alice", 100);
scores.Add("Bob", 80);
scores.Add("Charlie", 90);

// 딕셔너리에서 데이터 삭제
scores.Remove("Bob");

// 딕셔너리 데이터 출력
foreach(KeyValuePair<string, int> pair in scores)
{
    Console.WriteLine(pair.Key + ": " + pair.Value);
}

// 출력
// Alice: 100
// Charlie: 90

3. Stack

  • 후입선출(LIFO) 구조를 가진 자료 구조
// 스택 선언
Stack<int> stack1 = new Stack<int>();

// 스택에 데이터 추가
stack1.Push(1);
stack1.Push(2);
stack1.Push(3);

// 스택에서 데이터 가져오기
int value = stack1.Pop(); // value = 3 (마지막에 추가된 요소)

4. Queue

  • 선입선출(FIFO) 구조를 가진 자료 구조
// 큐 선언
Queue<int> queue1 = new Queue<int>();

// 큐에 데이터 추가
queue1.Enqueue(1);
queue1.Enqueue(2);
queue1.Enqueue(3);

// 큐에서 데이터 가져오기
int value = queue1.Dequeue(); // value = 1 (가장 먼저 추가된 요소)

5. HashSet

  • 중복값을 허용하지 않는 자료 구조
// 해시셋 선언
HashSet<int> set1 = new HashSet<int>();

// 해시셋에 데이터 추가
set1.Add(1);
set1.Add(2);
set1.Add(2); // 중복된 값이 있으므로 무시
set1.Add(3);

// 해시셋에서 데이터 가져오기
foreach (int element in set1)
{
    Console.WriteLine(element);
}

// 출력
// 1
// 2
// 3

0개의 댓글