배열

성혜·2024년 1월 17일
0

Java

목록 보기
6/25
post-thumbnail

배열, Array

자료구조 > 데이터 저장하는 물리적인 구조

데이터의 집합 > 변수들을 모아놓은 집합

같은 자료형을 저장하는 데이터의 집합

- 배열의 요소: 배열내의 방 하나(element)
  
- 배열의 길이: 배열내의 방의 개수(length)
  
- 배열의 첨자: 방의 순서(index)
  
- 배열의 최대 첨자 == 배열의 길이 - 1
  
- 배열의 첨자 잘못 사용 > ArrayIndexOutOfBoundException 발생

배열 자동 초기화

배열은 생성 직후 모든 요소(방)가 초기화가 된다.

초기화 규칙
1. 정수배열 > 0
2. 실수배열 > 0.0
3. 문자열 > \0(\u0000)
4. 논리배열 > false
5. 참조형배열 > null

  • 배열 형식
//배열 선언
자료형[] 배열명 = new 자료형[길이];

//요소의 접근
배열명[첨자] =; //쓰기
System.out.println(배열명[첨자]); //읽기

//초기화 리스트
자료형[] 배열명 = { 요소, 요소 요소 };

  • 배열 기본 예시
		// 요구사항] 학생 3명 > 국어 점수 > 총점, 평균
		// 추가사항] 학생수 증가 > 300명

		// 배열 선언하기
		// - 자료형[] 변수명 = new 자료형[길이];
		// - 배열타입 배열명 = new 배열타입[배열의길이];
		int[] kors = new int[5];

		// 배열의 방(요소, Element)에 접근 > 방 번호(첨자, Index) 사용
		kors[0] = 100;
		kors[1] = 90;
		kors[2] = 80;

		// int total = kors[0] + kors[1] + kors[2];
		int total = 0;

		for (int i = 0; i < kors.length; i++) {
			total += kors[i];
		}

		double avg = (double) total / kors.length; // 속성, 필드, 프로퍼티

		System.out.printf("총점: %d점, 평균: %.1f점\n", total, avg);
        


  • 배열 복사 (Side Effect)
		// 배열 복사(= 참조형 복사)

		// 값형 복사
		int a = 10;
		int b;

		b = a;

		// 값형 > 원본을 수정해도 복사본에 영향을 주지 않는다.
		// > Side effect가 발생하지 않는다.
		a = 20; // 원본 수정

		System.out.println("a: " + a);
		System.out.println("b: " + b);
		System.out.println();

		int[] nums = new int[3];

		nums[0] = 10;
		nums[1] = 20;
		nums[2] = 30;

		int[] copy;

		// int[] = int[]
		copy = nums;

		System.out.println(copy[0]);
		System.out.println(copy[1]);
		System.out.println(copy[2]);

		// 원본을 수정하면 복사본도 수정된다.
		// 복사본을 수정하면 원본도 수정된다.
		// > Side effect가 발생한다.
		nums[0] = 100;

		System.out.println(copy[0]);
		System.out.println(copy[1]);
		System.out.println(copy[2]);

		copy[1] = 200;

		System.out.println(nums[1]);
        
          
		// 배열 복사
		// 1. 얕은 복사, Shallow Copy
		// - 주소값 복사
		// - Side Effect 발생

		// 2. 깊은 복사, Deep Copy
		// - 실제 배열 복사
		// - Side Effect 발생 안함

		int[] nums = new int[3];

		nums[0] = 10;
		nums[1] = 20;
		nums[2] = 30;

		int[] copy = new int[3];

		for (int i = 0; i < nums.length; i++) {

			// 방과 방끼리의 복사 > 요소끼리의 복사
			// int = int
			copy[i] = nums[i];

		}

		nums[0] = 100;

		System.out.println(copy[0]);
        //깊은 복사
        //결과 : 10

=> 깊은 복사를 해주는 클래스가 있다!

Arrays 클래스

  • 유틸리티 클래스
  • 배열과 관련된 여러가지 기능을 구현한 클래스
  • 배열을 조작하는 편리한 기능을 제공하는 역할
		// Arrays 클래스
		// - 유틸리티 클래스
		// - 배열과 관련된 여러가지 기능을 구현한 클래스
		// - 배열을 조작하는 편리한 기능을 제공하는 역할

		int[] nums = new int[3];

		nums[0] = 10;
		nums[1] = 20;
		nums[2] = 30;

		// 배열의 상태를 확인?
		// - [I > int[]
		// - @
		// - 2ff4acd0 > 메모리 주소
		System.out.println(nums); // 쓸모없음

		printArray(nums);
		System.out.println(Arrays.toString(nums)); // dump(덤프)

		// *** C계열의 언어들은 범위를 나타날때
		// - 시작위치(inclusive) ~ 끝위치(exclusive)

		int[] copy;

		// 깊은 복사
		copy = Arrays.copyOfRange(nums, 0, nums.length);

		nums[0] = 100;
		System.out.println(Arrays.toString(nums));
		System.out.println(Arrays.toString(copy));
        
 //결과
[I@2ff4acd0
10 20 30
[10, 20, 30]
[100, 20, 30]
[10, 20, 30]


  • 배열 정렬
    : 크기 비교 후 재배치
정렬
- 크기 비교 후 > 재배치

1. 오름차순
a. 숫자: 작은수 > 큰수
b. 문자열 : 문자코드값 순
c. 날짜 시간 : 과거 > 미래

2. 내림차순
a. 숫자: 큰수 > 작은수
b. 문자열 : 문자코드값 역순
c. 날짜 시간 : 미래 > 과거

정렬 구현
1. 직접 구현 > 정렬 알고리즘
2. JDK 구현된 기능

버블정렬 + swap

swap > 두 공간의 데이터를 서로 바꾸는 작업
		int[] nums = { 5, 3, 1, 4, 2 };
		System.out.println(Arrays.toString(nums));

		//가장 큰 또는 작은 원소가 배열의 끝으로 이동
		for (int i = 0; i < nums.length; i++) { // 사이클(0,1,2,3)
			// 서로 인접한 두 원소를 비교하고 필요한 경우 위치 교환
			for (int j = 0; j < nums.length - 1 - i; j++) {

				// 오름차순
				if (nums[j] > nums[j + 1]) {
					temp = nums[j];
					nums[j] = nums[j + 1];
					nums[j + 1] = temp;
				}
			}
		}
		System.out.println("오름차순 정렬: " + Arrays.toString(nums));

		for (int i = 0; i < nums.length; i++) {
			for (int j = 0; j < nums.length - 1 - i; j++) {

				// 내림차순
				if (nums[j] < nums[j + 1]) {
					temp = nums[j];
					nums[j] = nums[j + 1];
					nums[j + 1] = temp;
				}
			}
		}

		System.out.println("내림차순 정렬: " + Arrays.toString(nums));


배열 조작

  • 삽입, 삭제
  • 비용 발생

1. 배열 요소 삽입(Insertion)

Right Shift > 오른쪽으로 한 칸씩 이동했다.
=> 값을 오른쪽에 복사 해놓음

삽입 이후의 요소들이 인덱스가 변경된다. (중요)

		int[] nums = { 1, 2, 3, 4, 5 };
		int index = 1;
		int value = 9;

		System.out.println("nums[0] = " + nums[0]);
		System.out.println("nums[3] = " + nums[3]);

		System.out.println(Arrays.toString(nums));

		for (int i = nums.length - 2; i >= index; i--) {
			// System.out.println(i);
			nums[i + 1] = nums[i];
			System.out.println(Arrays.toString(nums));
		}
		
		System.out.println();

		nums[index] = value;
		System.out.println(Arrays.toString(nums));

		System.out.println("nums[0] = " + nums[0]); //처음에 넣었던 값을 기억 못하면 큰일!
		System.out.println("nums[3] = " + nums[3]); //값이 바뀌는 데 에러는 안 떠있음 
        
 
//결과
nums[0] = 1
nums[3] = 4
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 4]
[1, 2, 3, 3, 4]
[1, 2, 2, 3, 4]

[1, 9, 2, 3, 4]
nums[0] = 1
nums[3] = 3

2. 배열 요소 삭제(Deletion)

Left Shift > 왼쪽으로 한칸씩 이동했다.

		int[] nums = { 1, 2, 3, 4, 5 };
		int index = 1;
		
		System.out.println(Arrays.toString(nums));
		
		for (int i=index; i <=nums.length-2; i++) {
			// System.out.println(i);
			nums[i] = nums[i+1];
			
		}
		
		nums[nums.length-1] =0; //맨 마지막 값 0으로 초기화
		System.out.println(Arrays.toString(nums));
        
//결과
[1, 2, 3, 4, 5]
[1, 3, 4, 5, 0]


  • 다차원 배열

    1차원 배열, 2차원 배열, 3차원 배열

		//1차원 배열
		int[] nums1 = new int[3];
		nums1[0] = 10;
		nums1[1] = 20;
		nums1[2] = 30;
		
		System.out.println(Arrays.toString(nums1));
		
		
		//2차원 배열
		int[][] nums2 = new int[2][3];
		
		nums2[0][0] = 10;
		nums2[0][1] = 20;
		nums2[0][2] = 30;
		
		nums2[1][0] = 40;
		nums2[1][1] = 50;
		nums2[1][2] = 60;
		
		//nums2 자료형? > int[][]
		//nums2[0] 자료형 > int[]
		//nums2[0][0] 자료형 > int
		
		nums2[0][1] = 20;
		System.out.println(nums2.length); //출력 : 2 
		System.out.println(nums2[0].length); //출력 : 3
		System.out.println(nums2[0][0]); //출력 : 10(int 값)
		
		
		System.out.println(Arrays.toString(nums2));
		System.out.println(Arrays.deepToString(nums2));
	 
		
		//2차원 배열 탐색
		for(int i=0; i<nums2.length; i++) {
			for(int j=0; j<nums2[0].length; j++) {
				System.out.print(nums2[i][j] + "\t");
			} // 하나의 층에 있는 배열 출력
			System.out.println();
		}
		
		System.out.println();
		
		//3차원 배열
		int[][][] nums3 = new int[2][2][3];
		
		nums3[0][0][0] =10;
		nums3[0][0][1] =20;
		nums3[0][0][2] =30;
		
		nums3[0][1][0] =40;
		nums3[0][1][1] =50;
		nums3[0][1][2] =60;
		
		nums3[1][0][0] =70;
		nums3[1][0][1] =80;
		nums3[1][0][2] =90;
		
		nums3[1][1][0] =100;
		nums3[1][1][1] =110;
		nums3[1][1][2] =120;
		
		
		for(int i=0;i<nums3.length;i++) {
			for(int j=0; j<nums3[0].length;j++) {
				for(int k=0; k<nums3[0][0].length;k++) {
					System.out.printf("%5d",nums3[i][j][k]);
				}
				System.out.println();
			}
			System.out.println();
		}
		
 //결과
[10, 20, 30]
2
3
10
[[I@2ff4acd0, [I@54bedef2]
[[10, 20, 30], [40, 50, 60]]
10	20	30	
40	50	60	

   10   20   30
   40   50   60

   70   80   90
  100  110  120

  • 배열 길이 정적 할당 VS 동적 할당

❗ 배열의 길이는 불변이다. ❗
=> 한번 만들어진 배열의 방은 더 늘리거나 삭제할 수 없다.

		Scanner scanner = new Scanner(System.in);
		
		System.out.print("학생수 : ");
		
		int lenght = scanner.nextInt();
		
		int[] kor = new int [lenght]; //동적으로 길이 할당
		
		System.out.println(kor.length);
profile
하루를 정리하고 기록합니다.

0개의 댓글