동일한 자료형의 값들이 연속적
으로 저장
되는 자료 구조
고정된 크기: 배열은 선언 시 정해진 크기를 변경할 수 없다. 이는 배열이 메모리에 연속적으로 할당되기 때문이다.
직접적인 메모리 접근: 배열의 각 요소는 고유한 인덱스를 가지며, 이를 통해 빠른 접근이 가능하다.
동일한 자료형: 배열에 저장되는 모든 요소는 동일한 데이터 유형을 가져야 한다.
// 배열 선언
데이터_유형[] 배열_이름;
// 배열 초기화
배열_이름 = new 데이터_유형[크기];
// 배열을 한 줄로 선언 및 초기화
데이터_유형[] 배열_이름 = new 데이터_유형[크기];
// 배열 요소에 접근
배열_이름[인덱스] = 값;
값 = 배열_이름[인덱스];
예시1)
int[] array1 = new int[5]; // 크기가 5인 int형 배열 선언
string[] array2 = new string[3]; // 크기가 3인 string형 배열 선언
int num = array1[0]; // 배열 첫 번째 요소에 접근
예시2)
int[] array1 = new int[5]; // 크기가 5인 int형 배열 선언
string[] array2 = new string[3]; // 크기가 3인 string형 배열 선언
int num = 0;
// 배열 초기화
array1[0] = 1;
array1[1] = 2;
array1[2] = 3;
array1[3] = 4;
array1[4] = 5;
num = array1[0]; // array1 배열의 첫번째 요소(인덱스 0의 값 1; 을 읽어 num에 저장
아이템 가격 예제)
int[] itemPrices = { 100, 200, 300, 400, 500 };
int totalPrice = 0;
for (int i = 0; i < itemPrices.Length; i++)
{
totalPrice += itemPrices[i];
}
Console.WriteLine("총 아이템 가격: " + totalPrice + " gold");
Length : 배열의 길이, 여기서는 100, 200, 300, 400, 500 이므로 총 5번 반복
// 플레이어의 공격력, 방어력, 체력, 스피드를 저장할 배열
int[] playerStats = new int[4];
// 능력치를 랜덤으로 생성하여 배열에 저장
Random rand = new Random();
for (int i = 0; i < playerStats.Length; i++)
{
playerStats[i] = rand.Next(1, 11);
}
// 능력치 출력
Console.WriteLine("플레이어의 공격력: " + playerStats[0]);
Console.WriteLine("플레이어의 방어력: " + playerStats[1]);
Console.WriteLine("플레이어의 체력: " + playerStats[2]);
Console.WriteLine("플레이어의 스피드: " + playerStats[3]);
int[] scores = new int[5]; // 5명의 학생 성적을 저장할 배열
// 성적 입력 받기
for (int i = 0; i < scores.Length; i++)
{
Console.Write("학생 " + (i + 1) + "의 성적을 입력하세요: ");
scores[i] = int.Parse(Console.ReadLine());
}
// 성적 총합 계산
int sum = 0;
for (int i = 0; i < scores.Length; i++)
{
sum += scores[i]; // 입력한 scores[i] 배열을 다 더해준다.
}
// 성적 평균 출력
double average = (double)sum / scores.Length;
Console.WriteLine("성적 평균은 " + average + "입니다.");
{
//배열을 활용한 숫자 맞추기 게임
Random random = new Random(); // 랜덤 객체 생성
int[] numbers = new int[3]; // 3개의 숫자를 저장할 배열
// 3개의 랜덤 숫자 생성하여 배열에 저장
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = random.Next(1, 10);
}
int attempt = 0; // 시도 횟수 초기화
while (true)
{
Console.Write("3개의 숫자를 입력하세요 (1~9): ");
int[] guesses = new int[3]; // 사용자가 입력한 숫자를 저장할 배열
for(int i = 0; i < guesses.Length;i++)
{
guesses[i] = int.Parse(Console.ReadLine());
}
int correct = 0;
for(int i = 0; i<numbers.Length;i++)
{
for(int j=0; j<guesses.Length; j++)
{
if (numbers[i] == guesses[j])
{
correct++;
break;
}
}
}
attempt++;
Console.WriteLine("시도 횟수" + attempt + " : " + correct + "개의 숫자를 맞추셨습니다.");
if (correct == 3)
{
Console.WriteLine("축하합니다. 모든 숫자를 맞추셨습니다.");
break;
}
}
}
}
// 2차원 배열의 선언과 초기화
int[,] array3 = new int[2, 3]; // 2행 3열의 int형 2차원 배열 선언
// 방법1. 다차원 배열 직접 초기화
// [행, 열]
array3[0, 0] = 1;
array3[0, 1] = 2;
array3[0, 2] = 3;
array3[1, 0] = 4;
array3[1, 1] = 5;
array3[1, 2] = 6;
//방법2. 다차원 배열 for문 초기화
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
array3[i, j] = i + j + 1; // i와 j의 합에 1을 더해 초기화
}
}
// 선언과 함께 초기화
int[,] array2D = new int[3, 4] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
// 3차원 배열의 선언과 초기화
int[,,] array3D = 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 } }
};
int[,] map = new int[5, 5];
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
map[i, j] = i + j;
}
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
Console.Write(map[i, j] + " ");
}
Console.WriteLine();
}
int[,] map = new int[5, 5]
{
{ 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 1 },
{ 1, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1 }
};
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
if (map[i, j] == 1)
{
Console.Write("■ ");
}
else
{
Console.Write("□ ");
}
}
Console.WriteLine();
}
Random random = new Random(); // 랜덤 객체 생성
int[] numbers = new int[3]; // 3개의 숫자를 저장할 배열
// 3개의 랜덤 숫자 생성하여 배열에 저장
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = random.Next(1, 10);
}
int attempt = 0; // 시도 횟수 초기화
while (true)
{
Console.Write("3개의 숫자를 입력하세요 (1~9): ");
int[] guesses = new int[3]; // 사용자가 입력한 숫자를 저장할 배열
// 사용자가 입력한 숫자 배열에 저장
for (int i = 0; i < guesses.Length; i++)
{
guesses[i] = int.Parse(Console.ReadLine());
}
int correct = 0; // 맞춘 숫자의 개수 초기화
// 숫자 비교 및 맞춘 개수 계산
for (int i = 0; i < numbers.Length; i++)
{
for (int j = 0; j < guesses.Length; j++)
{
if (numbers[i] == guesses[j])
{
correct++;
break;
}
}
}
attempt++; // 시도 횟수 증가
Console.WriteLine("시도 #" + attempt + ": " + correct + "개의 숫자를 맞추셨습니다.");
// 모든 숫자를 맞춘 경우 게임 종료
if (correct == 3)
{
Console.WriteLine("축하합니다! 모든 숫자를 맞추셨습니다.");
break;
}
}
자료를 모아놓은 데이터 구조
동적 크기 조정:
컬렉션은 요소를 추가하거나 제거할 때 크기가 동적으로 조정된다.
다양한 구조 제공:
List
, Dictionary
, Stack
, Queue:
, HashSet
등 다양한 종류의 컬렉션이 존재하며, 각각 특정 상황에 적합하게 사용된다.
유연한 데이터 관리:
컬렉션은 데이터 추가, 삭제, 검색 등 다양한 작업을 효율적으로 수행할 수 있도록 설계되었다.
- List는 가변적인 크기를 갖는 배열
- List에 담을 자료형을 지정하여 생성합니다.
List<int> numbers = new List<int>(); // 빈 리스트 생성
numbers.Add(1); // 리스트에 데이터 추가
numbers.Add(2);
numbers.Add(3);
numbers.Remove(2); // 리스트에서 데이터 삭제
foreach(int number in numbers)//list에 있는 것들을 number에 하나씩 끌어옴, 리스트 데이터 출력
{
Console.WriteLine(number);
}
for문 표현, 배열과 다르게 Count를 사용)
for(int i=0; i< list.Count; i++) // length가 아닌 count 사용
{
Console.WriteLine(list[i]); //list도 [] 인덱싱이 가능
}
배열은 Length
, 리스트는 Count
- 딕셔너리(Dictionary)는 키와 값으로 구성된 데이터를 저장
- 딕셔너리는 중복된 키를 가질 수 없으며, 키`(Key)`와 값`(Value)`의 쌍을 이루어 데이터를 저장
using System.Collections.Generic;
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);
}
KeyValuePair
: Key 값과 Value 값을 정해주기 위함, Dictionary와 함께 스인다.
Stack은 후입선출(LIFO) 구조를 가진 자료 구조로 요소를 저장하고 검색한다.
Stack<int> stack1 = new Stack<int>(); // int형 Stack 선언
// Stack에 요소 추가
stack1.Push(1);
stack1.Push(2);
stack1.Push(3);
// Stack에서 요소 가져오기
int value = stack1.Pop(); // value = 3 (마지막에 추가된 요소)
Queue는 선입선출(FIFO) 구조의 자료 구조.
Queue<int> queue1 = new Queue<int>(); // int형 Queue 선언
// Queue에 요소 추가
queue1.Enqueue(1);
queue1.Enqueue(2);
queue1.Enqueue(3);
// Queue에서 요소 가져오기
int value = queue1.Dequeue(); // value = 1 (가장 먼저 추가된 요소)
HashSet은 중복되지 않은 요소들로 이루어진 집합
HashSet<int> set1 = new HashSet<int>(); // int형 HashSet 선언
// HashSet에 요소 추가
set1.Add(1);
set1.Add(2);
set1.Add(3);
// HashSet에서 요소 가져오기
foreach (int element in set1)
{
Console.WriteLine(element);
}
🍳 배열과 컬렉션의 차이
특징 | 배열(Array) | 컬렉션(Collection) |
---|---|---|
크기 | 고정된 크기 | 동적으로 크기 조정 가능 |
메모리 할당 | 선언 시 할당 | 요소 추가/삭제 시 변경 |
데이터 유형 | 동일한 자료형만 저장 | 다양한 유형의 컬렉션 제공 |
접근 방식 | 인덱스를 통한 직접 접근 | 다양한 방법(인덱스, 키 등) |
사용 사례 | 고정된 데이터 세트 | 유동적인 데이터 세트 |
성능 | 빠른 데이터 접근 | 데이터 조작 유연성 |
메모리 관리: 배열은 정적인 크기를 가지지만, 컬렉션은 동적으로 크기가 조정된다. 따라서 컬렉션은 더 유연하지만, 때로는 추가적인 메모리 오버헤드가 발생할 수 있다.
사용 편의성: 컬렉션은 데이터를 추가하고 제거하기 쉽고, 다양한 유용한 메서드를 제공한다. 반면 배열은 기본적인 데이터 구조이므로, 수동으로 크기 관리와 데이터 조작을 해야 한다.
성능 측면: 배열은 데이터에 대한 접근이 빠르지만, 크기 변경이 불가능하다. 컬렉션은 크기 변경이 가능하지만, 특정 유형의 컬렉션(예: 리스트)에서는 데이터 접근이 배열보다 느릴 수 있다.
데이터 크기와 변동성: 고정된 크기의 데이터를 다룰 때는 배열을 사용하는 것이 좋다. 데이터 크기가 자주 변경되거나 다양한 작업을 수행해야 할 때는 컬렉션을 사용하는 것이 유리하다.
성능 요구 사항: 데이터 접근 속도가 중요한 경우 배열이 유리할 수 있다. 다양한 데이터 조작이 필요하거나 크기 조정이 자주 필요한 경우 컬렉션을 고려해야 한다.
🧃 배열과 리스트의 차이
리스트는 동적으로 크기를 조정할 수 있어 배열과는 다르게 유연한 데이터 구조를 구현
1. 메모리 사용량 증가:
리스트는 동적으로 크기를 조정할 수 있어 배열보다 많은 메모리를 사용합니다. 따라서, 많은 데이터를 다루는 경우 리스트를 무분별하게 사용하면 메모리 사용량이 급격히 증가하여 성능 저하를 유발할 수 있습니다.
2. 데이터 접근 시간 증가:
리스트는 연결 리스트(linked list)로 구현되기 때문에, 인덱스를 이용한 데이터 접근이 배열보다 느립니다. 리스트에서 특정 인덱스의 데이터를 찾기 위해서는 연결된 노드를 모두 순회해야 하기 때문입니다. 이러한 이유로, 리스트를 무분별하게 사용하면 데이터 접근 시간이 증가하여 성능이 저하될 수 있습니다.
3. 코드 복잡도 증가:
리스트는 동적으로 크기를 조정할 수 있기 때문에, 데이터 추가, 삭제 등의 작업이 배열보다 간편합니다. 하지만, 이러한 유연성은 코드 복잡도를 증가시킬 수 있습니다. 리스트를 사용할 때는 데이터 추가, 삭제 등의 작업을 적절히 처리하는 코드를 작성해야 하므로, 코드의 가독성과 유지보수성이 저하될 수 있습니다.
데이터의 크기와 사용 목적을 고려하여 배열과 리스트 중 적절한 것을 선택