Java - Quick Sort(퀵 정렬)/ 배열 실습
| Quick Sort(퀵 정렬)
퀵 정렬은 불안정 정렬에 속하며, 다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속한다.
장점
1) 속도가 빠르다.
2) 추가 메모리 공간을 필요로 하지 않는다.
단점
1) 정렬된 리스트에 대해서는 퀵 정렬의 불균형 분할에 의해 오히려 수행시간이 더 많이 걸린다.
2) 퀵 정렬의 불균형 분할을 방지하기 위하여 피벗을 선택할 때 더욱 리스트를 균등하게 분할할 수 있는 데이터를 선택한다.
EX) 리스트 내의 몇 개의 데이터 중에서 크기순으로 중간 값(medium)을 피벗으로 선택한다.
정렬 과정
1) 리스트 안에 있는 한 요소를 선택한다. 이렇게 고른 원소를 피벗(pivot) 이라고 한다.
2) 피벗을 기준으로 피벗보다 작은 요소들은 모두 피벗의 왼쪽으로 옮겨지고 피벗보다 큰 요소들은 모두 피벗의 오른쪽으로 옮겨진다.
(피벗을 중심으로 왼쪽: 피벗보다 작은 요소들, 오른쪽: 피벗보다 큰 요소들)
3) 피벗을 제외한 왼쪽 리스트와 오른쪽 리스트를 다시 정렬한다.
4) 분할된 부분 리스트에 대하여 순환 호출 을 이용하여 정렬을 반복한다.
5) 부분 리스트에서도 다시 피벗을 정하고 피벗을 기준으로 2개의 부분 리스트로 나누는 과정을 반복한다.
6) 부분 리스트들이 더 이상 분할이 불가능할 때까지 반복한다.
7) 리스트의 크기가 0이나 1이 될 때까지 반복한다.
package class02;
public class Quicksort {
static void quick_sort(int[] data, int start, int end) {
if(start>=end) {
return; //반환 값을 나를 호출한 위치로 전달
// 함수 즉시 종료
}
int pivot=data[start]; //기준값
int L = start+1; //기준값 옆
int H = end; //끝부분
while(true) {
while(pivot>data[L]) {
if(L==end) { //low 포인트가 끝까지 도달했다면
break; //탈출
}
L++; //index 범위를 ++,-- 할 때는 Exception에 유의해야
}
while(pivot<data[H]) {
if(H==start) { //high 포인트가 처음부분에 도달했다면
break; //탈출
}
H--; //index 범위를 --
}
System.out.println("L="+L+", H="+H);
//cross
if(L>=H) { //L이 H보다 크거나 같다면
int tmp = data[start]; //교환 알고리즘
data[start] = data[H];
data[H] = tmp;
for(int i=0;i<data.length;i++) {
System.out.print(data[i]+" ");
}
System.out.println();
System.out.println();
break;
}
int tmp = data[L];
data[L] = data[H];
data[H] = tmp;
for(int i=0;i<data.length;i++) {
System.out.print(data[i]+" ");
}
System.out.println();
System.out.println();
}
quick_sort(data, start, H-1);
quick_sort(data, H+1, end);
}
public static void main(String[] args) {
//재귀함수
int[] data = {5,1,9,10,4,2,7,3,6,8};
System.out.println("Data 초기 값");
for(int i=0;i<data.length;i++) {
System.out.print(data[i]+" ");
}
System.out.println();
System.out.println();
quick_sort(data, 0, data.length-1);
//메서드 시그니처 : 함수 3요소 > input, output, 기능
System.out.println("최종 값");
for(int i=0;i<data.length;i++) {
System.out.print(data[i]+" ");
}
System.out.println();
}
}

| 배열 실습
1. 정수를 입력받아 입력한 정수만큼의 랜덤정수를 저장한 배열생성
2. 랜덤 정수들은 1이상 50이하의 정수들로만 구성, 서로 중복되지 않는다.
3. 배열에 저장된 값들 출력
package test;
import java.util.Random;
import java.util.Scanner;
public class TEST_basic {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Random rand = new Random();
System.out.print("정수를 입력 해주세요. : ");
int lotto = sc.nextInt(); //정수 입력
//함수
int[] arr = new int[lotto]; //입력한 정수의 크기만큼 배열 생성
//함수
for(int i=0;i<arr.length;i++) { //i가 arr 길이만큼 반복 진행
arr[i] = rand.nextInt(50)+1; //1~50 사이의 랜덤 값 할당
for(int j=0;j<i;j++) { //j가 i만큼 반복
if(arr[i] == arr[j]) { //만약 두 값이 같다면
i--; //i에 1 감소시켜 랜덤값을 재 할당받는다.
}
}
}
//출력할 함수
System.out.print(lotto+"개의 랜덤 값 : ");
for(int i=0;i<arr.length;i++) { //i가 arr 길이만큼 돌아가는 동안
System.out.print(arr[i]+" "); //배열의 각 인덱스 값 출력
}
System.out.println();
}
}

심화
4번의 기능을 수행하는 함수를 정의하고 호출하여 사용
2,3의 기능을 수행하는 함수를 정의하고 호출하여 사용
package test;
import java.util.Random;
import java.util.Scanner;
public class TEST {
//Inout O, Output X
static void f1(int[] data) { //배열 출력하는 함수
System.out.print("랜덤 정수 값 : ");
for(int i=0;i<data.length;i++) { //i가 data 길이만큼 돌아가는 동안
System.out.print(data[i]+" "); //배열의 각 인덱스 값 출력
}
System.out.println();
}
//Input O, Output O
//랜덤 값 할당받는 함수
static int[] f2(int num) { //정수형 배열 반환하는 함수
Random rand = new Random();
int[] lottoNum = new int[num]; //입력한 정수의 크기만큼 배열 생성
for(int i=0;i<lottoNum.length;i++) { //i가 lottoNum 길이만큼 반복 진행
lottoNum[i] = rand.nextInt(50)+1; //1~50 사이의 랜덤 값 할당
for(int j=0;j<i;j++) { //j가 i만큼 반복
if(lottoNum[i] == lottoNum[j]) { //만약 두 값이 같다면
i--; //i에 1 감소시켜 랜덤값을 재 할당받는다.
}
}
}
return lottoNum;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num; //유효 범위
System.out.print("50이하의 정수만을 입력 해주세요 : ");
while(true) { //유효성 검사
num = sc.nextInt(); //정수 입력
if(num>50 || num<1) { //입력된 정수 값이 50 이상이라면
System.out.print("1이상, 50이하의 정수 값만 입력 해주세요. : ");
continue;
}
else {
break;
}
}
int[] lotto = f2(num); //함수 f2 호출
f1(lotto); //함수 f1 호출
}
}
다른 풀이
중복 건에 대해 범위가 정해져있지 않기 때문에 while문을 사용하는 것이 더 좋다
package test;
import java.util.Random;
import java.util.Scanner;
public class TEST {
//Inout O, Output X
static void f1(int[] data) { //배열 출력하는 함수
System.out.print("랜덤 정수 값 : ");
for(int i=0;i<data.length;i++) { //i가 data 길이만큼 돌아가는 동안
System.out.print(data[i]+" "); //배열의 각 인덱스 값 출력
}
System.out.println();
}
//Input O, Output O
//랜덤 값 할당받는 함수
static int[] f2(int num) { //정수형 배열 반환하는 함수
Random rand = new Random();
int[] lottoNum = new int[num]; //입력한 정수의 크기만큼 배열 생성
int i = 0;
while(i<lottoNum.length) {
int randNum = rand.nextInt(50)+1;
//랜덤 수를 우선 생성
// 기존의 배열에 랜덤수가 존재한다면, 다시 위로
// 존재 안하면, 아래로
boolean flag = false;
for(int j=0;j<i;i++) {
if(randNum==lottoNum[j]) {
flag = true;
break;
}
}
if(flag) {
continue;
}//중복 발생하지 않았으므로, 대입
lottoNum[i] = randNum;
i++;
}
return lottoNum; //lottoNum 값 반환
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num; //유효 범위
System.out.print("50이하의 정수만을 입력 해주세요 : ");
while(true) { //유효성 검사
num = sc.nextInt(); //정수 입력
if(num>50 || num<1) { //입력된 정수 값이 50 이상이라면
System.out.print("1이상, 50이하의 정수 값만 입력 해주세요. : ");
continue;
}
else {
break;
}
}
int[] lotto = f2(num); //함수 f2 호출
f1(lotto); //함수 f1 호출
}
}