변수가 엄청나게 많을 때, 변수들에 일일히 이름을 짓기는 어려울 겁니다.
복잡한 프로그램을 작성함에 따라 아주 많은 변수를 선언해야 하는데, 매번 이름을 붙여주지 않고 날로 먹을 수 있을까요?
int a,b,c,d,e,f,g,h...;
C++을 포함한 수많은 언어들에서는 이러한 문제를 "배열" 을 통해 해결하고 있습니다. 오늘은 배열에 대해서 알아보도록 하겠습니다.
배열(array)
일반적인 변수가 단독주택이라면 배열은 마치 아파트와 같아서,
위치,번호라는 개념이 존재한다는 것이 가장 큰 차이가 됩니다.
int A[10];
자료형 변수명[갯수];
A라는 이름을 가진 변수를 10개 선언했습니다.
C언어에서 []
대괄호는 배열에 접근할때 사용됩니다.
이 10개의 변수들은 순서대로
0번, 1번, 2번... 9번까지의 번호를 할당받습니다.
1부터 시작하지 않는다는 것에 주의해주세요
K번째 A 변수로의 접근은 A[K]
으로 가능합니다.
이러한 A[0]
, A[1]
각각의 변수들을 배열 A의 원소라고 부릅니다.
기본적으로 알고리즘 문제해결에서는 변수를 초기화하는것을 습관화 하시는것을 추천드리는데, 배열의 변수들을 초기화 하는 구문은 다음과 같습니다.
int Arr[5] = {1,2,3,4,5}; // [1,2,3,4,5]
int Arr2[5] = {1,2}; // [1,2,0,0,0]
int Arr3[5] = {0}; // [0,0,0,0,0]
초기화된 후의 결과는 주석을 통해 적어두었습니다.
첫 번째 구문의 경우 배열의 모든 자리에 들어갈 값을 모두 적어주었습니다.
두 번째 구문의 경우 배열의 일부분만을 초기화 하는데, 이 경우 모든 그 뒤의 값은 0으로 초기화됩니다.
이를 이용해서 세 번째 구문에서는 배열의 모든 값을 0으로 초기화하고 있습니다. 자주 사용하는 방법이니 기억해두시면 좋습니다.
배열의 크기를 알려주지 않는 선언 방법도 있습니다.
int Arr[] = {1,2,3,4}; // [1,2,3,4]
이러면 자동으로 크기가 4인 배열을 생성하고 그 안에 순서대로 1,2,3,4
를 채워넣습니다. 후에 쓸일이 있으니 이런게 있구나 정도만 기억해주세요.
배열의 잘못된 선언
크기가 N인 배열을 만들어보겠습니다.
일반적인 접근은 다음과 같습니다
int N;
cin >> N;
int Arr[N];
위 소스코드는 매우 그럴듯해 보이지만, 정상적으로 작동하지 않는 소스코드입니다. 프로그램이 처음 실행되는 직후 배열의 크기가 정해져야 하는데, N이 어떤 값인지 아직 입력해 넣지 않았기 때문입니다.
이럴때는 N의 최댓값, N이 아무리 커도 100은 넘지 않을것이다 의 100
을 찾으시고, 이를 이용해 배열을 선언하면 됩니다.
int N;
cin >> N;
int Arr[100];
배열을 왜 사용하는가
배열은 서로 같은 의미를 지닌 값들을 묶는데에 최적화되어있는 자료구조입니다. 여기서 말하는 의미란 배열의 각 원소 안의 숫자가 무엇을 나타내는지에 대한 의미입니다.
예를 들어, 10명의 몸무게를 입력받는다고 가정해 보겠습니다.
int weight0;
int weight1;
int weight2;
int weight3;
int weight4;
int weight5;
int weight6;
int weight7;
int weight8;
int weight9;
cin >> weight0 >> weight1 >> weight2 >> weight3 >> weight4;
cin >> weight5 >> weight6 >> weight7 >> weight8 >> weight9;
입력을 받아오는 cin 구문이 너무 길어져 두개로 분리했습니다.
이제 이 소스코드를 줄여보겠습니다.
똑같은 논리를 배열을 사용해 작성하면 아래와 같아집니다.
int weight[10];
cin >>weight[0]>>weight[1]>>weight[2]>>weight[3]>>weight[4];
cin >>weight[5]>>weight[6]>>weight[7]>>weight[8]>>weight[9];
배열과 반복문을 활용해보겠습니다.
int weight[10];
for(int i=0; i<10; i++){ // [0,9] 닫힌구간에서 반복
cin >> weight[i];
}
수십 줄의 긴 문장이 단 네줄로 정리되었습니다.
논리를 구성하고 문제를 해결하실 때, 같은 논리라면 보다 적은 소스코드를 가지는 쪽이 한번에 묶어서 "아 이 부분은 입력이구나" 하고 이해하기가 쉽습니다.
다차원 배열
지금까지의 배열은 일직선상에 나열된 주소들이라면,
2차원 평면 (x,y) 에 대한 배열을 생각해 보겠습니다
10x10 크기의 배열은
int arr[10][10];
으로 만들 수 있습니다.
초기화는 일반적 배열과 똑같으며,
앞에서 보았던 배열들을 축이 하나라는 의미에서 "1차원 배열",
지금 본 배열이 축이 두개라는 점에서 "2차원 배열"으로 부릅니다.
3차원 이상의 배열도 만들어 낼 수 있습니다.
결론
배열은 수많은 입력과 계산이 필요한 고난이도 알고리즘으로 갈수록 자주 사용하게 되는 핵심 개념 중 하나입니다.
반드시 익히는것을 추천드리며 일반적으로 N개의 수를 받아 저장하는데 쓰일 뿐만 아니라 다양한 사용법이 있음을 짚고 넘어가보아야 합니다.
오늘 보신 개념들로 문제 > 새싹 > 배열
부분을 해결하실 수 있으며,
그 중에서도 이 유형의 문제를 짚고자 합니다.
이 문제의 일반적인 접근법은
배열 Arr[5]
를 만들어 다섯대의 자동차 번호를 각각 저장 후,
반복문과 조건문을 활용해 각각의 자동차 번호가 금지된 번호와 같은지 비교해보는 방법이 있습니다.
#include <iostream>
using namespace std;
int main(){
int N;
int ans = 0;
int Arr[5];
cin >> N;
for(int i=0; i<5; i++){
cin >> Arr[i];
}
for(int i=0; i<5; i++){
if(Arr[i] == N){
ans++;
}
}
cout << ans;
return 0;
}
이 풀이보다 깔끔하게 문제를 해결할 수 있을까요?
지금부터 이런 배열을 정의해 보겠습니다Arr[K]
: 자동차 번호의 일의 자리 숫자가 K인 자동차의 댓수
일의 자리 숫자는 0~9 까지 총 10개 존재하므로
배열 Arr
은 10칸이어야 합니다.
또한, 입력받은 자동차 번호의 일의 자리 숫자가 N
이라고 한다면,Arr
배열의 N
번째 원소에 있는 숫자를 1 늘려서Arr[N]
이 자동차 댓수를 정확히 표시하도록 해주어야 합니다.
이를 소스코드로 옮기면 다음과 같습니다.
#include <iostream>
using namespace std;
int main(){
int N,K;
int Arr[10];
cin >> N;
for(int i=0; i<5; i++){
cin >> K;
Arr[K]++;
}
cout << Arr[N];
return 0;
}
문제에서 요구하는 10부제를 위반한 자동차의 대수는
다시 말해 금지된 번호와 일의 자리 숫자가 같은 자동차의 댓수이기 때문에,Arr[N]
안에 담겨있는 값이 정답이 됩니다.
이렇듯 배열에 어떤 값을 담고자 하느냐가 굉장히 중요하게 작용합니다.
본격적으로 소스코드 작성자의 논리에 따라 프로그램 소스코드의 길이, 실행시간 등이 바뀌게 되므로, 이 단계부터는 브론즈 V
난이도가 아닌, 브론즈 IV
이상의 난이도 문제를 많이 만나실 수 있을 것입니다.