배열

contability·2025년 7월 24일
0

자료구조

목록 보기
3/8

정의

배열은 같은 타입의 데이터를 연속된 메모리 공간에 순차적으로 저장하는 선형 자료구조다. 인덱스를 통해 각 요소에 직접 접근할 수 있다.

현실에 비유하자면

아파트 복도의 호실들

  • 101호, 102호, 103호... 순서대로 번호가 매겨져 있다
  • 특정 호실(인덱스)을 알면 바로 찾아갈 수 있다 - O(1) 접근
  • 하지만 중간에 새로운 호실을 만들려면 뒤의 모든 호실 번호를 바꿔야 한다 - O(n) 삽입
  • 연속된 공간에 배치되어 있어서 관리하기 쉽다

특징

전통적인 배열 vs JavaScript 배열

전통적인 배열 (C, Java 등)

  • 동일한 타입: 모든 요소가 같은 타입을 가진다
  • 고정 크기: 선언 시 크기가 결정된다
  • 연속된 메모리: 물리적으로 연속된 메모리 공간에 저장된다

JavaScript 배열

  • 동적 타입: 서로 다른 타입의 요소를 저장할 수 있다
  • 동적 크기: 런타임에 크기를 자유롭게 변경할 수 있다
  • 객체 기반: 내부적으로 객체로 구현되어 희소 배열이 가능하다

시간 복잡도

연산시간 복잡도설명
접근 (Access)O(1)인덱스를 통한 직접 접근
검색 (Search)O(n)선형 검색 필요
삽입 (Insert)O(n)중간 삽입 시 요소들을 이동
삭제 (Delete)O(n)중간 삭제 시 요소들을 이동

공간 복잡도

  • O(n): n개의 요소를 저장하는 공간 필요

JavaScript에서의 배열

// 배열 생성
const arr1 = [1, 2, 3, 4, 5];
const arr2 = new Array(5); // 크기가 5인 빈 배열
const arr3 = Array.from({length: 5}, (_, i) => i + 1);

// 기본 연산
arr1[0]; // 접근: O(1)
arr1.indexOf(3); // 검색: O(n)
arr1.push(6); // 끝에 삽입: O(1)
arr1.unshift(0); // 앞에 삽입: O(n)
arr1.splice(2, 0, 2.5); // 중간 삽입: O(n)
arr1[10] = 'z';        // 중간 인덱스들은 자동으로 undefined

다양한 타입 저장 가능

// 여러 타입을 하나의 배열에 저장
const mixedArray = ['문자열', 42, true, null, {name: '객체'}, [1, 2, 3]];

동적 크기 조절

const arr = [1, 2, 3];
arr.push(4);        // 길이 증가
arr.pop();          // 길이 감소
arr.length = 10;    // 직접 길이 설정

희소 배열 지원

const sparse = [1, , , 4];  // 인덱스 1, 2는 비어있음
console.log(sparse.length); // 4
console.log(sparse[1]);     // undefined

TypeScript에서의 타입 정의

// 기본 타입 배열
const numbers: number[] = [1, 2, 3];
const strings: Array<string> = ['a', 'b', 'c'];

// 다양한 타입을 Union 타입으로 명시
const typedArray: (string | number | boolean)[] = ['문자', 13, false];

// 튜플 (고정 크기, 다양한 타입)
const tuple: [string, number, boolean] = ['hello', 42, true];

// 읽기 전용 배열
const readonlyArr: readonly number[] = [1, 2, 3];

장점

  • 빠른 접근: 인덱스를 통한 O(1) 접근 시간
  • 메모리 효율성: 연속된 메모리 사용으로 캐시 친화적
  • 간단한 구현: 직관적이고 구현이 쉽다

단점

  • 고정 크기: 정적 배열의 경우 크기 변경 불가
  • 비효율적 삽입/삭제: 중간 위치의 삽입/삭제 시 O(n) 시간
  • 메모리 낭비: 미사용 공간이 있을 수 있다

활용 사례

  • 데이터 저장: 순서가 있는 데이터 집합 저장
  • 행렬 연산: 2차원 배열로 행렬 표현
  • 버퍼: 고정 크기의 임시 저장 공간
  • 룩업 테이블: 인덱스 기반 빠른 조회

프론트엔드에서의 활용

// 컴포넌트 리스트 렌더링
const items = ['사과', '바나나', '오렌지'];
const itemElements = items.map((item, index) => (
  <li key={index}>{item}</li>
));

// 상태 배열 관리
const [todos, setTodos] = useState([]);
const addTodo = (todo) => setTodos([...todos, todo]);
const removeTodo = (index) => setTodos(todos.filter((_, i) => i !== index));

최적화 팁

  • 자주 삽입/삭제가 발생하는 경우 연결 리스트 고려
  • 큰 배열의 검색이 빈번한 경우 정렬 후 이진 검색 활용
  • 고정 크기 데이터는 Array보다 TypedArray 고려 (Float32Array, Int32Array 등)

0개의 댓글