헬린코린이

[JAVA] 배열 본문

Programming/Java

[JAVA] 배열

HCD 2022. 11. 14. 21:40

배열이란

 - 동일한 자료형(Data Type)의 데이터를 연속된 공간에 저장하기 위한 자료구조이다. 즉, 연관된 데이터를 그룹화하여 묶어준다고 생각하면 된다.

 

배열의 장점에는

 연관된 데이터를 저장하기 위한 변수의 선언을 줄여주며, 반복문 등을 이용하여 계산과 같은 과정을 쉽게 처리할 수 있다.

배열을 선언하는 방법은

타입[] 변수명 = new 타입[배열 크기]
변수[0] = 값;
변수[1] = 값;

이 방법과 

타입[] 변수명 = {값1,값2,값3};

 

바로 선언과 동시에 초기화를 할 수 있다.

변수의 선언은 이렇게 하고

다음은 변수의 꽃이라고 할 수 있는 length를 알아보겠다.

	
	
		
		int[] data = new int[5];

		Random rand = new Random();
		for(int i = 0; i<5; i++) {
			data[i]=rand.nextInt(101);
		}
		for(int i =0; i<5; i++) {
			System.out.println();
		}

예를 들어 이런 코드가 있다고 가정해보자 

int타입의 배열을 5개를 선언해줬다.

그리고 for문을 이용해 i <5; 까지 2번 돌렸다.

이렇게 코드를 작성해도 작동은 할 텐데

배열의 길이를 늘여야 하는 상황이 생겨 배열의 길이를 늘여주었다.

그렇게 된다면 for문의 조건문도 바꿔야 할 것이다

그렇게 되면 3번을 바꿔야 하는데 만약 이게 여러 개가 있다고 가정해보자

하나하나 다 바꿀 것인가? 만약에 못 바꾼 곳이 있다면 그걸 찾는 데까지는 시간이 많이 소요될 것이다.

그래서 우리는 length라는 걸 선언해줄 것이다.

	
	
		
		int[] data = new int[5];

		Random rand = new Random();
		for(int i = 0; i<length; i++) {
			data[i]=rand.nextInt(101);
		}
		for(int i =0; i<length; i++) {
			System.out.println();
		}

이렇게 된다면 length를 선언해주면 배열을 바꿔주기만 한다면

다른 것은 다 바꿀 필요가 없을 것이다

그러면 저 한 번으로 끝을 낼 수 있다.

 

배열 정렬에는 여러 가지 정렬이 있는데 버블 정렬부터 보겠다(더 배우는 대로 추가할게요)

		int[] data = new int[5];
		data[0]=3;
		data[1]=1;
		data[2]=5;
		data[3]=4;
		data[4]=2;

		for(int a = 0; a<data.length; a++) {
			for(int i = 0; i<data.length-1; i++){//데이터 개수만큼 반복 
				// 예외 나는 닝는 -1을 안써서 자기 자신은 안 돌아야한다? 꼭 다 쓰는데 마무리가 안된다.
				if(data[i]>data[i+1]) {
					int tmp = data[i];
					data[i]= data[i+1];
					data[i+1]=tmp;
				}

이 코드는 배열중에서 가장 작은 순서를 앞으로 오게 하고 큰 수를 뒤로 가게 하는

정렬이다 정렬에는 여러 가지에 정렬이 있는데

이 정렬은 교체 버블 정렬이라고 한다.

코드는 보면 금방 이해할 수 있으리라 본다.

 

삽입 정렬이란 배열의 자기 자신의 값과 바로 이전에 값을 비교해서 어느 것이 큰지 확인하고 바꾸면서

진행되는 정렬이다.

package class06;

import java.util.*;

public class Test05 {

	public static void main(String[] args) {

		int[] arr = {3,1,5,2,7};

		for(int i=1;i<arr.length;i++) {	
			int tmp=arr[i];				
			int index=i-1;	
			System.out.println(i+"회전 정렬");
			 		
					
			while(index>=0 && arr[index] > tmp) {	
				arr[index+1]=arr[index];
				index--;
				System.out.println(Arrays.toString(arr));
			} 
			
			arr[index+1]=tmp;	
			
			System.out.println(i+"-1회전 정렬\n"+Arrays.toString(arr));
			
		}
		System.out.println("정렬 끝\n"+Arrays.toString(arr));

		
	}
}

이해하기 쉽게 변수명은 arr과 index로 지정했다.

가볍게 설명하자면 for문의 초기화 값을 1로 지정한 이유는

0보다 이전에 값을 비교하지 않을뿐더러 굳이 0으로 지정할 이유는 없어서이다

비교하고자 하는 값을 tmp변수를 선언해 따로 저장해둔다 

그리고 앞 배열의 값을 가지고와 while문으로 두 값을 비교하고

만약 이전 값이 크다면 이전 값을 현재 값에다가 저장하고

현재 값에다가 tmp에서 저장한 값을 다시 지정해준다.

간단히 설명하면 이런 로직을 가지고 있고 코드를 참고해서 어떻게 돌아가는지 생각해보면

금방 쉽게 이해될 것이다.

 

퀵 정렬에 알아보겠다.

현존하는 정렬 중 가장 빠른 정렬이다

퀵 정렬은 분할-정복 과정을 거친다.

우선 코드를 보고 알아보겠다.

	public static void main(String[] args) {
		int[] data = new int[10];
		data[0]=4;
		data[1]=1;
		data[2]=10;
		data[3]=2;
		data[4]=8;
		data[5]=7;
		data[6]=9;
		data[7]=3;
		data[8]=6;
		data[9]=5;
		for(int v:data) {
			System.out.print(v+" ");
		}
		System.out.println();

		quickSort(data,0,data.length-1);
		for(int v:data) {
			System.out.print(v+" ");
		}
	}
	public static void quickSort(int[] data, int start,int end) {
		if(start>=end) {//더 이상 분할 되지 않을떄
			return;
		}
		int pivod = data[start];//맨 왼쪽에 있는 데이터
		int L=start+1;
		int H=end;

		while(L<H) {


			while(data[L]<pivod) {	//
				L++;
			}

			while(data[H]>pivod) {
				H--;
			}

			if(L>H) {//크로스
				break;
			}

			int tmp=data[L];
			data[L]=data[H];
			data[H]=tmp;
		}
		int tmp = data[start];
		data[start]=data[H];
		data[H]=tmp;
		
		
		quickSort(data, start, H-1);
		quickSort(data, H+1, end);
	}

우선  배열을 생성해 숫자를 지정해주고 quicksort() 메서드를 생성한다. 재귀 함수를 사용하기에

종료 조건을 만들어 준다.

정말 이해하기 쉽게 이야기하겠다.

배열의 맨 처음 숫자를 pivot == 기준점으로 잡아준다.

이제 L값과 H값을 지정해줘야하는데 처음에는 기준점 바로 뒤에 값을 L로  지정해주고

배열 끝 값을 H로 지정해준다. 이제 하나씩 while문을 이용해 확인한다.

기준값보다 L값이 클 떄까지 배열을 돌아준다. 그렇게 되면

2번 index에서 멈춘다 그리고 H값은 기준값보다 낮을 때까지 끝에서 0번 index까지 확인한다.

그렇게 되면 7번 index에서 멈춘다 그럼 이때

둘의  값을 교체해준다. 아래 교체 로직도 정의되어 있다.

그리고 교체를 완료하면 마저 일을 진행한다. L값은 기준값보다 큰 값을 찾고

H값은 기준값보다 작은 값을 찾는다 그렇게 찾다가 보면

L은 4번 index를 가리키고

H는 3번 index를 가리킨다.

이렇게 되면 Cross 즉 교차가 발생하는데

이때 기준값이랑 H값이랑 교체를 해준다. 그러면

기준값은 무조건 자기 자리로 정렬된다. 이걸 1회전 정렬이라고 부른다

디버깅 표를 한번 보겠다. 그럼 이해가 쉬울 것이다.

더보기

[4 1 10 2 8 7 9 3 6 5]

4 1 10 2 8 7 9 3 6 5

p L                       H

4 1 10 2 8 7 9 3 6 5

p     L              H

4 1 3 2 8 7 9 10 6 5

p    L              H

4 1 3 2 8 7 9 10 6 5

p       H L                ⇒CROSS(교차)

2 1 3 4 8 7 9 10 6 5

p        H L              ⇒CROSS(교차) : 1회전 정렬

그리고 이제 기준점 4를 기준으로 앞 뒤 값들을 이전에 알고리즘을 사용하여 정렬한다.

그리고 출력을 해보면 정렬이 된 모습을 볼 수 있을 것이다.

 

 

 

배열을 초기화하고 그 배열에 값을 알아보기 위해 값을 탐색하는 방법이 있는데

그중 하나가 이진 탐색(이분 검색)이라고 한다.

 

검색의 전제조건으로는 데이터가 정렬된 상태여야 가능하다는 것이다.

	int L  = 0;
				int H = lotto.length-1;
				while(true) {
					
					int M = (L+H)/2;
					if(num==lotto[M]) {
						System.out.println("index: "+M);
						break;
					}else if(num>lotto[M]) {
						L=M+1;
					}else {
						H=M-1;
					}
					if(L>H) {
						System.out.println(num+"은 없습니다...");
						break;
					}
				}

이 코드가 이진 탐색 코드인데 여러 가지 방법 중 이런 방법도 있다고 참고하시면 될 것 같다.

L을 0으로 H을 배열 길이로 초기화하고

M이라는 변수를 만들어 L과 M을 2로 나눈 것으로 초기화하였다

 

그리고 무한 반복문을 돌아 if문을 만나게 되면 내가 찾고 있는 숫자가 입력받은 숫자와 같다면 멈추고

입력받은 숫자가 크면 L변수에 M+1을 해준다 즉 처음 반복문을 돌 때 L이 0이고 H를 10이라고 가정했을 때

M은 5이다 그래서 L변수에 5+1을 다시 초기화시켜주면 다음 반복문 돌 때 5부터 10 사이에서 검색을 시작한다.

이렇게 하면 배열의 길이가 100이든 1000이든 검색시간은 엄청 빨라질 것이다.

로또를  출력하는 예제를 만들어보았다.

package class01;

import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;

public class Test03 {
	public static void main(String[] args) {

		Random rand = new Random();
		Scanner sc = new Scanner(System.in) ;
		System.out.print("저장할 랜덤수 입력: ");
		int rNum = sc.nextInt();
		int[] rdNum = new int[rNum];

		System.out.print("범위입력: ");
		int range = sc.nextInt();

		int checkIndex = 0;
		if(rNum>range) { //while문 하나 따로 만들기 난  while문 하나로 해결하려고 함
			System.out.println("범위가 랜덤수를 초과할수 없습니다.");
			return; 
		} 
		while(true) {
			int rdrange = rand.nextInt(range)+1;// 안으로 안 집어넣음
			boolean flag = false;
			for(int i = 0; i<checkIndex; i++) {
				if(rdrange==rdNum[i]) {
					flag=true;
					break;
				}
			}

			if(!flag) { //이해 안감 //조건식 false인데 !으로 true로 바꿔 if문 안에 문장을 실행
				rdNum[checkIndex]=rdrange;
				checkIndex++;
			}else {
				continue;
			}


			if(checkIndex==rdNum.length) {
				break;
			}
		}
		System.out.println("중복없는 랜덤값: "+Arrays.toString(rdNum));

		for(int j = 0; j<rdNum.length; j++) {
			for(int i = 0; i<rdNum.length-1; i++) {
				if(rdNum[i]<rdNum[i+1]) { //min으로 초기화 하려고 함 바보
					int tmp = rdNum[i+1];
					rdNum[i+1]=rdNum[i];
					rdNum[i]=tmp;
				}
			}
		}
		System.out.println("내림차순: "+Arrays.toString(rdNum));

	}
}

이 코드에는 중복제거와 내림차순의 코드를 추가하였다.

 

배열을 선언하고 초기화하고

배열을 출력을 해야 하는데 출력에는 두 가지 방법이 있다

첫 번째는 for문을 이용해서 출력하는 방법이 있고

두 번째는 Arrays.toString(); 이 있다.

 

Comments