- 메서드(객체지향 1번째 원칙)
- 2차원 배열
- 버블정렬, 선택정렬, 삽입정렬, 퀵솔트
- 로또
2차원 배열
ctrl + d
행 복사 붙여넣기

누적. 우변부터 읽어서 count 선언부터 해야 함.
for문 안에 넣으면 count가 계속 0이 되서 안됨
코드 덩어리 : 모듈
seats[0].length : 열의 개수
seats.length : 행의 개수
println해서 해보면 됨.
package ex03;
public class TheaterSeats {
public static void main(String[] args) {
//배열은 구조 변경 불가능
int[][] seats = {
{0,0,0,1,1,0,0,0,0,0},
{0,0,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,1,1,1,0},
{1,1,0,0,0,0,1,1,1,0},
};
int sum = 0;
int count = 0;
//int row = -1;
for (int row = 0; row < seats.length ; row++) {
count = 0;
for(int i=0; i< seats[row].length; i++){
count = count + seats[row][i];
}
System.out.println(row+"번째 행의 관객수는 : " +count);
sum = sum + count;
}
System.out.println("전체 관객수는 :" +sum);
// row++;
// count = 0;
// for(int i=0; i< seats[row].length; i++){
// count = count + seats[row][i];
// }
// System.out.println(row+"번째 행의 관객수는 : " +count);
// sum = sum + count;
//
// row++;
// count = 0;
// for(int i=0; i< seats[row].length; i++){
// count = count + seats[row][i];
// }
// System.out.println(row+"번째 행의 관객수는 : " +count);
// sum = sum + count;
//
// row++;
// count = 0;
// for(int i=0; i< seats[row].length; i++){
// count = count + seats[row][i];
// }
// System.out.println(row + "번째 행의 관객수는 : " +count);
// sum = sum + count;
//
// row++;
// count = 0;
// for(int i=0; i< seats[row].length; i++){
// count = count + seats[row][i];
// }
// System.out.println(row + "번째 행의 관객수는 : " +count);
// sum = sum + count;
//
//
//
// System.out.println("전체 관객수는 :" +sum);
}
}
하나하나 단계(for문도 다 적어보고 고쳐보자)를 밟아가면서 하자.
버블 정렬
알고리즘이란 무엇일까?
컴퓨터가 따라 할 수 있도록 문제를 해결하는 절차나 방법을 자세히 설명하는 과정.
-추상적으로 일을 못 시키고 자세하게 말해줘야 함.
-함수를 이용하여 추상적으로 일을 시킬 수 있음
ex) 함수(라면 끓여와.)
- 버블 정렬(bubble sort) 알고리즘의 개념 요약 서로 인접(붙어있는)한 두 원소(인덱스)를 검사하여 정렬하는 알고리즘 인접한 2개의 레코드를 비교하여 크기가 순서대로 되어 있지 않으면 서로 교환한다. 선택 정렬과 기본 개념이 유사하다. https://gmlwjd9405.github.io/2018/05/06/algorithm-bubble-sort.html
- 버블 정렬(bubble sort) 알고리즘의 구체적인 개념 버블 정렬은 첫 번째 자료와 두 번째 자료를, 두 번째 자료와 세 번째 자료를, 세 번째와 네 번째를, … 이런 식으로 (마지막-1)번째 자료와 마지막 자료를 비교하여 교환하면서 자료를 정렬한다. https://gmlwjd9405.github.io/2018/05/06/algorithm-bubble-sort.html
ex) 5,8,2,4,3(원본 데이터)라면,
[1회전 (4바퀴)]
(1 라운드) 5, 8 비교(변화없음)
(2 라운드) 8,2비교 (5,2,8,4,3)
이후에는 변화된 (5,2,8,4,3)을 비교
(3 라운드) 8,4비교 (5,2,4,8,3)
(4 라운드) 8,4비교 (5,2,4,3,8)
4번 ⇒ 1회전
[2회전(3바퀴)]
1) 5,2 비교(2,5,4,3,8)
2) 5,4 비교(2,4,5,3,8)
3) 5,3 비교(2,4,3,5,8)
3번 ⇒ 2회전
[3회전(2바퀴)]
1) 2,4비교(2,4,3,5,8)
2) 4,3비교(2,3,4,5,8)
지금의 상황에서는 운 좋게 여기서 끝났음
[4회전(1바퀴)]
상황에 따라 3,2,4,5,8이 되어 있을 수 있으니
1)2,3을 비교(2,3,4,5,8)
3,4,8,2,5라고 순서만 다른 경우였다면,
1) (3,4,8,2,5)
2) (3,4,8,2,5)
3) (3,4,2,8,5)
4) (3,4,2,5,8)
가장 큰 수를 끝에 둚
두번 째는 두번째 큰 수를 끝 앞에 두는 것
5,8,2,4,3 (N)
회전 수 : N-1
1회전 비교 횟수 : N-1
2회전 비교 횟수 : N-2
3회전 비교 횟수 : N-3
4회전 비교 횟수 : N-4
*자바 문법
상수는 대문자로

*스왑

* 디버깅



그 칸에 해당 하는게 맞는 지 확인 (bubbletest06)번호에 클릭 > 벌레 클릭
chat gpt 무료로 쓸 수 있음 :wrtn.ai
static으로 찾을 때는 클래스명으로 찾음

함수, 메서드


정렬의 목적
찾기 편하게
ex) 5.7.9.10.15.3
⇒ 10을 찾는 과정
첫번째부터 쭉 봄
4번만에 찾음, 그리고 뒤에 또 있을 수 있으니 끝까지 체크(full scan) ⇒효율이 n
⇒최악의 과정
⇒
ex2) 5.7.9.10.15.3
⇒ primary (유일)⇒ so 4번만 하면 끝
여기서는 숫자가 5,7,9,15,3,10이면 최악.
ex) 5.7.9.10.15.3⇒ 정렬 ⇒ 3,5,7,9,10,15
크기 [6]
6/2 =3번지 먼저 search 9니까 왼쪽방향은 안봐도 됨
⇒10,15,3 3칸에서 /2해서 … 9를 0부터 기준에서 찾음?-v
정렬하면 이진트리 가능, 클러스트링이 있어서 중복있어도 빠름
이진트리, 바이너리서치가 가능함.
⇒ 선형적으로(비례해서) 증가하지 않고 로그방식으로 증가?!(천천히 늘어남)-v
클러스트링
5,9,10,3,4,3,2
->정렬 ->2,3,3,4,5,9,10
군집화 가능, search 빨라짐

주말에 도전해보셈

선택 정렬
선택 정렬은 첫 번째 자료를 두 번째 자료부터 마지막 자료까지 차례대로 비교하여 가장 작은 값을 찾아 첫 번째에 놓고, 두 번째 자료를 세 번째 자료부터 마지막 자료까지와 차례대로 비교하여 그 중 가장 작은 값을 찾아 두 번째 위치에 놓는 과정을 반복하며 정렬을 수행한다.
1회전을 수행하고 나면 가장 작은 값의 자료가 맨 앞에 오게 되므로 그 다음 회전에서는 두 번째 자료를 가지고 비교한다. 마찬가지로 3회전에서는 세 번째 자료를 정렬한다.
https://gmlwjd9405.github.io/2018/05/06/algorithm-selection-sort.html
5,8,2,4,3
기준점 p=0(place), 바뀌어야 하는 위치final i=0
5,8(0 p값,1번지 비교)
5,2(0,2) p=2
2,4(2,3)
2,3(3,4)
if(i !=p)2,8,5,4,3(i,p교환)
1라운드 후⇒ 5,8,2,4,3인데 ⇒ 2,8,5,4,3(i와 p교환)
교환 인덱스 p=1(place), 바뀌어야 하는 위치final i=1
(i와 p가 동일시 변경x)
2,8,5,4,3에서
8,5(1,2번지 비교) p=2로 변경됨
5, 4비교(2,3) p=3
4,3(3,4) p=4
if(i !=p) 2,3,5,4,8(i,p교환)
교환 인덱스 p=2(place), 바뀌어야 하는 위치final i=2
final i = 2(해당위치변경), p=2(교환 인덱스)
5,4 (2,3) p=3
4,8(3,4)
if(i !=p) 2,3,4,5,8
final i = 3(해당위치변경), p=3(교환 인덱스)
5,4 (3,4)
if(i !=p) x
*이 과정에서 공식, 규칙 find
버블정렬 연습문제_내가 연습
{1,2,3,4,5,6,7,8,9}
1회전]
(1,2) 비교 ⇒ 변화x
(2,3) 비교 ⇒ 변화x
(3,4) 비교 ⇒ 변화x
(4,5) 비교 ⇒ 변화x
(5,6) 비교 ⇒ 변화x
(6,7) 비교 ⇒ 변화x
(7,8) 비교 ⇒ 변화x
(8,9) 비교 ⇒ 변화x
⇒{1,2,3,4,5,6,7,8, 9} 9확정
2회전]
(1,2) 비교 ⇒ 변화x
(2,3) 비교 ⇒ 변화x
(3,4) 비교 ⇒ 변화x
(4,5) 비교 ⇒ 변화x
(5,6) 비교 ⇒ 변화x
(6,7) 비교 ⇒ 변화x
(7,8) 비교 ⇒ 변화x
⇒{1,2,3,4,5,6,7, 8, 9} 8확정
3회전]
(1,2) 비교 ⇒ 변화x
(2,3) 비교 ⇒ 변화x
(3,4) 비교 ⇒ 변화x
(4,5) 비교 ⇒ 변화x
(5,6) 비교 ⇒ 변화x
(6,7) 비교 ⇒ 변화x
⇒{1,2,3,4,5,6, 7, 8,9} 7확정
…
8회전(8+7+6+5+4+3+2+1) ⇒ 총 36번
find rule ⇒ 숫자가 9개(n)면 n-1회전, n!번?-v
정렬의 목적 ⇒ 검색
검색의 기본 ⇒ 풀스캔
풀스캔이 좋은가?최악인가?
이진검색
정렬이 되어있는 상태에서 개수/2
package ex03.test;
public class BinaryTest01 {
public static void main(String[] args) {
//이진 검색 => 반드시 정렬이 되어 있어야 한다.
int[] arr = {1,2,3,4,5,6,7,8,9}; // 9(갯수)/2=4 =>4번지 정중앙 find -> 8을 찾고자 함
//target =8
//0~8번지비교
// mid = N/2= 4(index 위치값) -> arr[4]=값 5
//if(8 ==5) -> mid 위치에 타겟이 있다.
//if(8>5) 참->
// 5번지[mid+1]부터 8번지까지 비교
//mid = 7=arr[7]->값 8
//if(8 ==5) -> mid 위치에 타겟이 있다.
//if(8>8)
}
}
package ex03.test;
public class BinaryTest01 {
public static void main(String[] args) {
// 이진 검색 => 반드시 정렬이 되어 있어야 한다.
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // 9 / 2 = 4
// target = 8
// start=0 ~ end = 8
// // mid = N/2 = 4 -> arr[4] -> 값 5
// // if(8==5) -> mid 위치에 타겟이 있다.
// // if(8>5) 참
//
//
// // start=5 (mid+1) ~ end=8
// // mid = 7 = arr[7] -> 값 8
// // if(8==8) -> mid 위치에 타겟이 있다.
// // if(8>8)
//
//
// // target = 3
//
// // start=0 ~ end = 8
// // mid = N/2 = 4 -> arr[4] -> 값 5
// // if(3==5) -> mid 위치에 타겟이 있다.
// // if(3>5) 거짓
//
//
// // start=0 ~ end = mid-1
// // mid = 7 = arr[7] -> 값 8
// // if(8==8) -> mid 위치에 타겟이 있다.
// // if(8>8)
}
}
- 시간복잡도(최악으로 검색하는 횟수) : 풀스캔,선형적으로 늘어남
수가 늘어나면 너무 큰 수는 int로는 부족할 수 있다.
그래서
2의 8승 = 256
2의 16승 = 65536
2의 4승 = 16
=> 수를 8승, 16승, 4승으로 나타내면 편함=> log사용함
ex> 2의 50000승을 log를 이용하여 간단하게 표현할 수 있다.
시간복잡도는 log 밑이 2
log 2의 n
- 이진트리는 값들이 늘어나도 시간복잡도가 선형적으로 늘지 않음. 검색횟수가 완전 적고(O(logN)) 장점이다.
ex) 데이터 1억번.. 만번.. (풀 스캔 O(N)보다)
log2(42억 9천) = 32번 안에
//정렬이 되있든 안되있든 풀 스캔을 하면
* 이 정도는 외우자! (단위를 쉽게 알수 있게)
2^8 = 256
2^10 = 1024
2^16 = 65,536
2^32 =42억 9천~~~


데이터가 많을 수록 풀스캔보다 이진트리가 유리
적을 때는 풀스캔이 유리-v
package ex03;
public class BinarySearch {
public static void main(String[] args) {
// N = 21
// 시간복잡도 log2(N) -> log2(21) -> 4.xx (max. 뭘 찾는 지에 따라 최대 5번(올림 시킴)만에 찾는 다는 이야기 함.)
// 이진 검색 => 반드시 정렬이 되어 있어야 한다.
// 16 / 2*2*2*2*2 -> logn -> log17
int[] arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
int N = arr.length;
final int target = 3;
int start = 0;
int end = N - 1;
int mid;
int round = 1;
while (true) {
// 1 회전
mid = start + ((end - start) / 2); // 기대값 7
System.out.println("mid: " + mid);
if (arr[mid] == target) {
System.out.println(round + "회전 : " + target + "값은 " + mid + "번지에 있습니다");
break;
}
if (arr[mid] < target) { // 기대값 start 5, end 8
start = mid + 1;
}
if (arr[mid] > target) {
end = mid - 1;
}
System.out.println(round + "회전 start : " + start);
System.out.println(round + "회전 end : " + end);
round++;
}
System.out.println("시간복잡도 : " + (Math.log(N) / Math.log(2)));
}
}
자료를 2개를 찾을 때(예를 들어, 3,5를 찾을 때는)는 위의 경우 시간 복잡도가 5+5=10 / 3 개는 15, / 4 개는 20/ 5 개는 25 걸림. 근데 풀 스캔은 21번이니까 5개 자료 찾을 때는 풀 스캔이 유리. (필요한 데이터가 전체 데이터의 15%미만인 경우 (랜덤 액세스가)(바이너리가)(이진서치) 유리함. )
(랜덤액세스 vs 풀스캔)
풀스캔 처음부터 보는 것
퀵솔트
퀵 정렬은 이름 그대로 매우 빠르게 정렬을 수행하는 알고리즘이다. 기본적으로 분할정복의 성격을 가지고 있고 실제로도 많이 사용되는 대표적인 정렬 알고리즘이다.
Algorithm Concept
퀵 정렬은 다음과 같은 과정으로 정렬을 진행한다. 정렬은 오름차순으로 진행한다고 가정하자.
- 주어진 배열에서 하나의 요소를 선택하고 이를 pivot(피벗) 으로 삼는다.
- 배열 내부의 모든 값을 검사하면서 피벗 값보다 작은 값들은 왼쪽에, 큰 값들은 오른쪽에 배치한다.
- 이렇게 하면 배열이 두 부분으로 나뉜다. 나뉜 이 두 개의 배열에서 각각 새로운 피벗을 만들어서 두개의 배열로 다시 쪼개어 준다.
- 더 이상 배열을 쪼갤 수 없을 때까지 진행한다.
이 과정은 분할 정복의 원리를 이용한 것이다. 피벗을 중심으로 문제를
분할
하고, 피벗을 기준으로 해서 작은 값과 큰 값을 나열하는 정복
과정을 거친 뒤, 모든 결과를 결합
해서 큰 전체 문제를 해결한다.Example
퀵소트 알고리즘이 어떻게 동작하는지 자세히 알아보자.

Phase 1

일단 피봇을 선정하고 피벗보다 더 작은값과 더 큰 값을 탐색할 low 와 high 를 피벗을 제외한 배열의 양끝점에 둔다.
Phase 2

먼저 low를 계속 움직이면서 배열 요소를 검사해보자. 한칸 이동했을 때 low는 배열요소 9를 만나게 되는데, 이 값은 피벗값인 5보다 큰 값이다. low의 뒤에는 항상 피벗보다 작은 값이 있어야 하기 때문에 여기서 일단 멈춘다.
Phase 3

low가 멈추면 high를 움직인다. high를 한칸 옮기면 배열 요소 1에 도착하게 되는데 이 값은 피벗값인 5보다 작은 값이기 때문에 high의 영역에 있으면 안된다. high 도 여기서 일단 정지시킨다.
Phase 4

low 와 high가 모두 중단되면 중단된 위치를 먼저 확인해본다. 만약 low 와 high가 서로 위치가 역전된 상태가 아니라면 중단된 지점에 있던 두 요소를 교환한다. 따라서 1과 9가 교환되었다.
Phase 5

다시 low를 이동시킨다. 이번에도 역시 확인한 배열요소가 피벗보다 큰 값을 가지고 있기 때문에 중단한다.
Phase 6

이제 high 를 이동시키자. high도 새로 검사한 배열의 요소가 피벗보다 작은 값을 가지고 있기 때문에 현 위치에서 중단한다.
Phase 7

low 와 high 가 아직 교차하지 않기 때문에 두 배열 요소를 교환한다.
Phase 8

low가 한번 더 이동하면 피벗보다 큰 값을 만나기 때문에 다시 또 중단하게 된다.
high도 한번 더 이동하면 피벗보다 작은 값을 만나기 때문에 중단하게 된다.
이번 경우에는 low와 high의 위치가 역전됐기 때문에 교환되지 않고 정렬을 끝낸다.
Phase 9

1차로 정렬이 끝나면 피벗으로 설정된 배열요소를 high가 가르키는 배열요소와 교환해준다. 이제 피벗을 중심으로 왼쪽과 오른쪽에 피벗보다 작고 큰 값들이 위치했음을 확인할 수 있다.
More...
피벗을 중심으로 나뉘어진 두 그룹은 두 개의 배열처럼 취급되어서 위에서 거쳤던 과정을 똑같이 거칠 수 있다. low가 만들어낸 그룹의 피벗은 3이 될 것이고, high 가 만들어낸 그룹의 피벗은 7이 될 것이다. 이 작업을 분할된 배열의 길이가 1이나 0이 될 때까지 계속 반복한다.
implement
#include <stdio.h>
int partition (int arr[], int p, int r){
int low, high;
int pivot = arr[p]; // pivot 값 설정
low = p + 1; // low 는 pivot의 바로 다음 위치에서부터
high = r; // high는 전달된 끝지점
while(low <= high){
while(arr[low] < pivot) low++; // pivot 보다 작은 값이 나올때마다 이동
while(arr[high] > pivot) high--; // pivot 보다 큰 값이 나올때마다 이동
if (low <= high){ // low와 high 가 중단된 지점이 서로 위치가 역전된 지점이 아니라면
int temp = arr[low]; // low 와 high 의 값 변경
arr[low] = arr[high];
arr[high] = temp;
}
}
// 피벗과 high 위치 교환
int temp = arr[p];
arr[p] = arr[high];
arr[high] = temp;
return high; // 피벗 위치 반환
}
void quick_sort(int arr[], int left, int right){
if (left < right){
int pivot = partition(arr, left, right);
quick_sort(arr, left, pivot-1); // 피벗을 기준으로 왼쪽 배열 정렬
quick_sort(arr, pivot+1, right); // 피벗 기준으로 오른쪽 배열 정렬
}
}
int main (){
int arr [] = {3, 2, 1, 5, 7, 9, 6};
quick_sort(arr, 0, sizeof(arr)/sizeof(arr[0])-1);
for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]) ; i++){
printf("%d ", arr[i]);
}
}
5
신고하기
구독하기이 글은 본 저작자 표시, 비영리 규칙 하에 배포할 수 있습니다. 자세한 내용은 Creative Commons 라이선스를 확인하세요.
Creative Commons본 저작자 표시비영리
참고자료)
‣
Share article