[자료구조] 01. Java 기본 자료구조 - 배열
안녕하세요🖐️
이번 시간에는 자료구조 중에서도 기본 자료구조인 배열에 대해 자세히 알아보려고 합니다~
프로그램을 작성할 때, 데이터를 효율적으로 관리하고 사용하는 것은 프로그램의 성능을 크게 좌우합니다. 배열은 여러 데이터를 하나의 이름 아래 순차적으로 저장하여 관리할 수 있게 해주는 매우 기본적이면서도 중요한 자료구조입니다. 배열을 통해 우리는 데이터 집합을 효율적으로 처리할 수 있는 기반을 마련할 수 있습니다.
배열의 개념을 정확히 이해하고, 어떻게 활용할 수 있는지를 알아보는 것은 프로그래밍 학습의 첫걸음을 떼는 데 있어 매우 중요합니다. 배열을 사용함으로써 코드의 재사용성을 높이고, 효율적인 데이터 관리 방법을 배울 수 있습니다.
그럼 자료구조의 기본 중의 기본, 배열에 대해 함께 배워보는 시간을 가져보겠습니다!
배열이란?
배열은 동일한 자료형(type)의 구성 요소들을 연속적인 메모리 위치에 순차적으로 저장하는 구조입니다. 배열은 여러 데이터를 하나의 이름으로 그룹화하여 관리할 수 있게 해주며, 각 데이터 요소에는 고유한 인덱스(또는 위치)가 할당됩니다. 구성요소의 자료형은 어떤 형이든 상관없습니다.
예를 들어, int형 배열은 아래와 같은 방식으로 선언할 수 있습니다.
int[] a; // a는 자료형이 int형인 배열 : A 형식
int b[]; // b는 자료형이 int형인 배열 : B 형식
💡 단순한 int형이 아니라 int형인 배열임을 명확하게 나타내는 A 형식을 훨씬 많이 사용합니다.
- 예제 코드 -
int[] a = new int[5]; // 길이가 5인 int형 배열 생성 후 변수 a가 참조합니다.
위 예제는 int형의 데이터를 저장할 수 있는 길이가 5인 배열을 생성하고, 이 배열을 변수 a가 참조하도록 합니다. 이 과정을 통해 a는 배열의 시작 주소를 가리키게 되며, 배열의 각 요소에 접근하여 데이터를 저장하거나 읽을 수 있게 됩니다.
아래의 그림은 위 예제 코드의 배열을 나타낸 그림입니다.
배열의 구성 요소
배열의 개별 구성 요소에 접근하는 방법은 대괄호('[ ]') 연산자를 사용하여 정수형 인덱스를 명시하는 것입니다. 이 인덱스는 배열 내에서 각 요소의 위치를 나타냅니다. 배열의 인덱스는 0부터 시작합니다. 즉, 배열의 첫 번째 요소는 0번 인덱스에, 두 번째 요소는 1번 인덱스에 위치하고 이런 식으로 계속됩니다.
예를 들어, 길이가 5인 int형 배열 a가 있다면, 이 배열의 각 요소는 a[0], a[1], a[2], a[3], a[4]를 통해 접근할 수 있습니다. 여기서 a[0]은 배열의 첫 번째 요소를 나타내고, a[4]는 배열의 다섯 번째이자 마지막 요소를 나타냅니다.
int[] a = new int[5]; // 길이가 5인 int형 배열 생성 후 변수 a가 참조합니다.
a[2] = 10; // 배열의 인덱스는 0부터 시작하니, 세번째 요소에 10을 할당합니다.
System.out.println(a[2]); // 배열의 3번째 요소를 출력합니다. 결과는 10 입니다.
배열 요소에 접근하는 이 방식은 배열 내 특정 위치의 데이터를 읽거나 수정할 때 사용됩니다. 예를 들어, 위와 같은 코드는 배열 a의 세 번째 요소에 10을 할당하고 출력합니다. 이렇게 배열 요소에 값을 할당하거나 해당 요소의 값을 사용할 수 있습니다.
💡 단 배열 인덱스를 사용할 때는 배열의 범위를 초과하지 않도록 주의해야 합니다. 배열 a의 경우, 유효한 인덱스는 0부터 4까지이며, a[5]와 같이 배열의 범위를 벗어난 접근을 시도하면 오류가 발생합니다. 이는 배열이 고정된 크기를 가지며, 선언 시에 지정된 크기를 넘어서는 접근을 허용하지 않기 때문입니다.
배열의 길이
배열의 길이는 length 라는 속성을 통해 확인할 수 있습니다. a 배열의 길이를 확인하고 싶을 경우 아래와 같이 확인할 수 있습니다.
int[] a = new int[5]
System.out.println(a.length); // 배열의 길이를 반환합니다. 결과는 5 입니다.
배열의 구성 요소 초깃값
배열을 생성할 때 각 구성 요소에 기본으로 넣어지는 값을 초깃값이라 합니다. 변수를 명시적으로 초기화하지 않았을 때 프로그램의 안정성을 위해 자동으로 할당됩니다.
다음은 각 자료형의 초깃값을 정리한 표입니다.
배열의 명시적 초기화
배열 본체의 생성과 동시에 각 요소의 초깃값을 설정 할 수 있습니다. 아래의 코드는 배열 선언과 동시에 명시적으로 초깃값을 할당하는 코드입니다.
int[] a = {1, 2, 3, 4, 5}; // 배열 초기자에 의해 생성
int[] b = new int[] {1, 2, 3, 4, 5}; // new 연산자를 통해 좀 더 명확하게 선언
위의 예시에서 int[] a와 int[] b는 기능적으로 동일합니다. int[] b의 경우에는 new 키워드가 사용되어 명시적으로 배열 객체가 생성됨을 나타내고 있습니다. 이는 때때로 코드의 가독성을 높이거나, 특정 상황(예: 익명 배열 생성)에서 필요할 수 있습니다.
명시적 초기화를 할 때 배열의 길이를 별도로 지정하지 않습니다. 초깃값을 제공함으로써 배열의 길이는 자동으로 결정됩니다.
다차원 배열
배열을 구성 요소로 하는것을 2차원 배열이라 하고, 2차원 배열을 구성 요소로 하는 것을 3차원 배열이라 합니다. 이런 배열은 다차원 배열이라고 합니다. 다차원 배열 가운데 가장 간단한 것은 2차원 배열입니다.
int[][] a = new int[2][4];
이렇게 선언한 배열 a는 2행 4열 의 2차원 배열입니다.
그림으로 좀 더 명확하게 확인해보겠습니다.
2차원 배열안의 각 요소는 [ ] 을 2중으로 적용한 식 a[i][j]로 접근합니다.
실습 예제를 통해 위 내용을 적용해보겠습니다.
- 실습 예제 -
public class IntArray2D {
public static void main(String[] args) {
int a[][] = new int[2][4]; // 2행 4열의 2차원 배열 선언
a[0][2] = 12; // a[0][2]에 12 대입
a[1][0] = 8; // a[1][0]에 8 대입
a[1][3] = 26; // a[1][3]에 26 대입
for(int i = 0; i < 2; i++) // 2차원 배열의 각 요소 값 출력
for(int j = 0; j < 4; j++)
System.out.println("a["+i+"]["+j+"] = " +a[i][j] );
}
}
- 출력 결과 -
a[0][0] = 0
a[0][1] = 0
a[0][2] = 12
a[0][3] = 0
a[1][0] = 8
a[1][1] = 0
a[1][2] = 0
a[1][3] = 26
배열의 특징
- 고정 크기 : 대부분의 프로그래밍 언어에서 배열은 생성 시점에 크기가 고정됩니다. 배열의 크기는 런타임 동안 변경할 수 없으며, 이는 배열의 단점 중 하나로 여겨질 수 있습니다.
- 동일한 데이터 타입 : 배열에 저장된 모든 요소는 동일한 데이터 타입을 가져야 합니다. 이는 메모리를 효율적으로 관리하고, 배열 요소에 접근하는 속도를 높이는 데 도움이 됩니다.
- 인덱스 접근 : 배열의 요소에 접근하기 위해서는 인덱스를 사용합니다. 인덱스는 보통 0부터 시작하여 배열의 크기 - 1까지 번호가 매겨집니다. 이를 통해 배열의 어떤 요소에도 상수 시간 내에 접근할 수 있습니다(O(1)).
배열의 장점과 단점
장점
- 빠른 데이터 접근 : 인덱스를 통해 배열의 각 요소에 직접 접근할 수 있으므로, 데이터 검색에 걸리는 시간이 매우 짧습니다.
- 메모리 효율성 : 배열은 연속적인 메모리 공간에 데이터를 저장하기 때문에 메모리를 효율적으로 사용합니다. 또한, 오버헤드가 적어 다른 자료구조에 비해 공간 효율성이 높습니다.
단점
- 고정된 크기 : 배열은 생성 시 고정된 크기를 가지며, 크기를 동적으로 조정할 수 없습니다. 따라서 배열의 크기를 변경하려면 새로운 배열을 생성하고 데이터를 복사해야 합니다.
- 삽입 및 삭제의 비효율성 : 배열에서 요소를 삽입하거나 삭제하는 작업은 비효율적입니다. 특히, 배열의 시작 부분에 요소를 추가하거나 삭제할 때는 나머지 모든 요소를 이동시켜야 하므로, 이러한 작업의 시간 복잡도는 O(n)입니다.
이번 글을 통해 여러 데이터를 순차적으로 저장하는 자료구조 중 하나인 배열의 기본 개념과 사용 방법에 대해 알아보았습니다. 배열을 사용함으로써 우리는 데이터를 효율적으로 관리하고 접근할 수 있으며, 이는 데이터를 다루는 데 있어 매우 중요한 기술입니다. 배열을 통해 우리는 반복문과 같은 제어문을 사용하여 데이터를 쉽게 처리할 수 있고, 다양한 알고리즘을 구현하는 기반을 마련할 수 있습니다. 프로그래밍에서 배열을 효과적으로 사용하기 위해서는 이러한 기본적인 개념뿐만 아니라, 배열을 활용한 다양한 문제 해결 방법에 대해서도 계속해서 학습하고 실습하는 것이 중요합니다.
읽어주셔서 감사합니다 😊