8. 자바의 메소드
재귀적 함수호출
재귀적 함수호출은 자신의 함수를 호출하는 것이다.
내가 나를 불러내는 것. 프로그래밍할 시 정말정말 많이 쓰이는 기능이다.
예시) 시계 - 시간이라는 것은
package oop0524;
public class Test01_Method {
public static void test(){ //함수를 정의한 부분
test(); //내가 나를 불렀음, 재귀적 호출
}//test() end
public static void main(String[] args) {
//재귀적 함수 호출
//-> 자신이 자신의 함수를 호출
}//main end
}//class end
메소드 문법 잘 숙지하기
▶ 풀이
test함수안에서 test();을 선언하였다.
함수안에 함수명(); 이런 식으로 자신의 함수를 자신이 다시 호출할 수 있다.
이를 재귀함수라고 한다.
이런 식으로 사용한다.
package oop0524;
public class Test01_Method {
public static void test(){ //함수를 정의한 부분
test(); //내가 나를 불렀음, 재귀적 호출
}//test() end
public static long fact(int a){
if(a==0){
return 1;
}
else{
return a*fact(a-1); //내가 다를 다시 불러서 이용했다.
}
}//fact() end
public static void main(String[] args) {
//재귀적 함수 호출
//-> 자신이 자신의 함수를 호출
long result = fact(3); //result변수의 반환값이 있다. 자료형존재
System.out.println(result);
}//main end
}//class end
a=3 if(3==0)
else return 3*fact(3-1)
a =2 if(2==0)
else return 2*fact(2-1)
a=1 1 if(1==0)
else return 1*fact(1-1)
a=0 if(0==0) 1
a값이 계속 달라지고 있다.
그 다음 *연산을 반복한 후 if문조건을 만족할때 1 return하고 종료.
▶ 풀이
fact라는 자료형 long을 리턴하는 함수를 선언하고 매개변수를 정수 a로 받는다.
만일 a값이 0과 같다면 1을 리턴하고,
그 외는 a값과 fact(a-1)을 곱한 값을 다시 리턴한다. 여기서 fact함수안에서 fact함수를 다시 호출한 형태가 된다.
곱셈의 반복이 진행될 수록 값이 엄청 커질 수 있으므로 long으로 해주었다.
자바 클래스(.class) 실행순서
재귀함수는 이렇게 자신이 자신을 호출할 수 있는 함수라고 했다.
이런 식으로 main 함수를 부를 수도 있지 않을까. 함수니까 그러나.. 다른 함수와 다르게
사용자가 임의의 호출 불가능하다.
-> 클래스가 실행될 때.
-> 자바가상머신 (Java Virtual Machine)
-> 호출한다.
자바가상머신/
학습모듈에 있는 걸 전부 수업하지는 않음.
main()함수 호출 후 .class 실행
---------------------------------------------------
JVM(이란 가상머신이 상주) -> Javaw.exe
Java는 OS를 가리지 않는다. 플랫폼이 독립되어있다.
메모리안에 JVM을 설치하고 -> 실행
컴퓨터를 실행할때 운영체제(OS)가 제일 먼저 불러짐.
OS가 메모리에 상주하게 되면 컴퓨터로 여러가지 일을 수행할 수 있다.
보조기억장치에 있는 걸 RAM으로 불러와서 작업한 후 보조기억장치에 다시 기억.
main()함수
자바가상머신/
public static void main(String[] args)
이클립스에서도 테스트할 수 있지만 DOS로 테스트해보기.
Plus 클래스틀 만들어서 DOS로 실행해보았다.
copy - 복사
del - 삭제
rename - 이름수정
type Plus.java - 메모장수정..?
자바는 다른 것을 끌어다 쓴다.
그래서 환경변수를 설정해줘야한다.
환경변수 설정하기
- 환경변수 설정하지 않으면 컴파일 안됨.
- 내컴퓨터->속성->고급 시스템 설정->설정변경
-> 고급-> 환경변수-> 시스템변수 ->
① JAVA_HOME 환경변수 C:\Program Files\Java\jdk1.8.0_161
JAVA_HOME - DOS변수
② Path 편집 (삭제 절대 안됨)
마지막 문장 뒤에 ; 추가 -> ;%JAVA_HOME%\bin
③ CLASSPATH 환경변수 (콘솔창에서 자바클래스를 직접 실행할 경우 추가)
.;%JAVA_HOME%\lib\tools.jar;
④ 자바버전확인 : 시작-> cmd -> java -version
*환경변수 설정하기 찾아서 해보기.
* ; (세미콜론)으로 구분.
언제 어디서나 자바를 인식시키기 위해 경로잡는 것이다.
초기 환경설정 때 경로설정하는 것 매우매우매우 중요.
자바설치경로 c드라이브 root경로로 해놓는 게 좋다.
클래스 이름 정할때 예약어스러운 것들은 피하기.
Plus 클래스명에 문제가 있었어서 MainTest로 변경하였다.
public class MainTest {
public static void main(String[] args) {
System.out.println("main()함수에 값 전달 연습");
for(int idx=0; idx<args.length; idx++){
System.out.println(args[idx]);
}
}//main end
}//class end
idx는 1차원배열의 갯수만큼 증가반복.
CMD에 MainTest 클래스에 SEOUL JEJU BUSAN을 쳐주고 실행했더니
값이 들어와서 For문이 실행되었다.
이 값은 어떤 값이든 들어갈 때 대부분 String값으로 들어간다.
다른 값을 넣어주었을 때도 동일하게 적용이 된다.
String 값으로 들어가므로 위의 5 4 3은 "5" "4" "3"과 같다.
대부분의 언어에서 핸드폰번호,우편번호 등이 숫자처럼 생겼지만 String형으로 관리한다.
-> 그렇게 해야 관리하기 쉽기 때문에.
메소드 오버로딩
메소드 오버로딩은 함수명의 중복정의이다.
package oop0524;
public class Test02_OverLoading {
public static void print(int a){
System.out.println(a);
}//print end
public static void print(int a, int b){ //동일한 이름의 함수가 선언되었지만 오류가 아니다.
}//print end
public static void main(String[] args) {
}//main end
}//class end
함수명 print가 두번 선언되었지만 오류가 나지 않았다.
단, 무언가 두 함수가 다름을 알 수 있는 것이 있어야한다.
위와 같은 경우는 매개변수의 갯수가 달랐다.
그래서 함수 print를 각각 다른 함수로 인식한다.
자바를 배우면서 구조화된 시스템을 많이 마주하게 될 것이다.
자동으로 세팅이 다 되어져있다는 것.
함수명을 같이 써도 오류가 생기지 않으려면 (다른 함수로 인식되게 하려면)
1) 매개변수의 갯수가 다를 때
2) 매개변수의 자료형이 다를 때
package oop0524;
public class Test02_OverLoading {
//1번
public static void print(int a){
System.out.println(a);
}//print end
//2번
public static void print(int a, int b){ //동일한 이름의 함수가 선언되었지만 오류가 아니다.
System.out.println(a);
System.out.println(b);
}//print end
//3번
public static void print(double a){
System.out.println(a);
}//print end
//4번
public static void print(double a, double b){
System.out.println(a);
System.out.println(b);
}//print end
//5번
public static int print(int a){ //오류발생
}//print end
public static void main(String[] args) {
print(3); //1번
print(2,4); //2번
print(5.6); //3번
print(7.2,8.3); //4번
}//main end
}//class end
*함수의 리턴형은 오버로딩의 대상이 아니다.
그러므로 함수의 리턴형을 다르게 한다고 함수명 중복이 용인되는 것이 아님.
api에서 오버로딩은 어디서부터 어디까지 사용할 수 있는지 알려줌.
System.out.println(Math.abs(3)); //int
System.out.println(Math.abs(5L)); //long
System.out.println(Math.abs(1.2f));//float
System.out.println(Math.abs(4.6d));//double
Sort 정렬
특정한 키를 기준으로 순서대로 재배치하는 것을 sort 정렬이라고 한다.
정렬의 유형
1. 오름차순 ascending ASC
예) 1,2,3,4... 또는 ㄱㄴㄷㄹㅁ.... 1->10 , 알파벳이라면 대->소 (알파벳 아스키코드값이 대문자가 더 작기 때문에)
2. 내림차순 descending DESC
예) 5,4,3,2,1... 또는 ㅎ->ㄱ
* DB에서 가져올때는 DB에서 자료를 정렬해서 자바로 가져온다.
그렇지 않으면 아주 골치아파짐.
9 7 5 3 1 -> 1 3 5 7 9
a a+1
if ( > ) {tmp=a, a=b, b=tmp}
정렬의 방법
1. 삽입정렬 (insertion sort)
각 숫자를 적절한 위치에 삽입하는 방법으로 문제해결하는 알고리즘.
기본적으로 '정렬이 되어있다고 가정'한다는 점에서 특정경우에 따라 굉장히 빠른 속도 자랑.
삽입정렬의 시간 복잡도는 O(N^2)
2. 선택정렬 (selection sort)
가장 작은 것을 선택해서 제일 앞으로 보내는 알고리즘
가장 원시적이고 기초적인 방법
앞부분 부터 정렬된다.
선택정렬의 시간 복잡도는 O(N^2)
9 7 5 3 1 -> 1 3 5 7 9
9 7 5 3 1
7 9 5 3 1
5 9 7 3 1
3 9 7 5 1
1 9 7 5 3
----------- 1회전 완
1 7 9 5 3
1 5 9 7 3
1 3 9 7 5
----------- 2회전 완
1 3 7 9 5
1 3 5 9 7
----------- 3회전 완
1 3 5 7 9
----------- 4회전 완 //4회전 만에 오름차순 정렬되었다.
n-1 단계만에 sort가 되었다.
3. 버블정렬 (bubble sort)
뒤부터 차례차례 정렬되기 시작한다.
9 7 5 3 1 -> 1 3 5 7 9
9 7 5 3 1
7 9 5 3 1
7 5 9 3 1
7 5 3 9 1
7 5 3 1 9
----------- 1회전 완
5 7 3 1 9
5 3 7 1 9
5 3 1 7 9
----------- 2회전 완
3 5 1 7 9
3 1 5 7 9
----------- 3회전 완
1 3 5 7 9
----------- 4회전 완 // 정렬완료
//정렬 알고리즘
int[] su = {9,7,5,3,1};
int tmp;
//연습문제 1) selection sort 알고리즘을 이용해서
//오름차순 정렬 후 출력하시오.
System.out.print("선택정렬 오름차순은: ");
for(int a =0; a<su.length-1; a++){ //-1 들어가야함
for(int b=a+1; b<su.length; b++){ //자기자신과 비교할 필요가 없기 때문에 a+1 부터.
if(su[a]>su[b]){ //크기 비교해서
tmp = su[b]; //tmp변수에 작은 값을 넣기
su[b] = su[a]; //작은 값 있던 위치에 큰 값을 넣기
su[a] = tmp; //큰 값 있던 위치에 아까 임시로 tmp에 넣었던 작은 값을 넣기
}//if end
}//for end
}//for end
for(int a = 0; a<su.length; a++){
System.out.print(su[a]+" ");
}
System.out.println();
System.out.println("------------------------------");
//연습문제 2) bubble sort 알고리즘을 이용해서
//내림차순 정렬 후 출력하시오.
System.out.print("버블정렬 내림차순은: ");
for(int a =0; a<su.length-1; a++){ //뒤 부터 정렬이기 때문에?
for(int b=a+1; b<su.length; b++){ //자기자신과 비교할 필요가 없기 때문에 a+1 부터.
if(su[a]<su[b]){ //b는 a+1이니까 a가 b(a+1)보다 작으면 뒤로
tmp = su[a]; //작은 값이 뒤로 밀리는. swap
su[a] = su[b];
su[b] =tmp;
}//if end
}//for end
}//for end
for(int a = 0; a<su.length; a++){
System.out.print(su[a]+" ");
}
//결과값
// 선택정렬 오름차순은: 1 3 5 7 9
// ------------------------------
// 버블정렬 내림차순은: 9 7 5 3 1
부등호의 위치에 따라 정렬방향이 달라진다.
■ 선생님 답안 ■
//연습문제 1) selection sort 알고리즘을 이용해서
//내림차순 정렬 후 출력하시오.
System.out.print("선택정렬 오름차순은: ");
for(int a=0; a<su.length-1; a++){
for(int b=a+1; b<su.length; b++){
if(su[a]>su[b]) { //오름차순
int tmp=su[a];
su[a]=su[b];
su[b]=tmp;
}//swap
}
}//for end
for(int idx=0; idx<su.length; idx++){
System.out.print(su[idx]+" ");
}//for end
System.out.println();
//결과값
//1 3 5 7 9
//연습문제 2) bubble sort 알고리즘을 이용해서
//내림차순 정렬 후 출력하시오.
System.out.print("버블정렬 내림차순은: ");
for(int a = 3; a>=0; a--){
for(int b=0; b<=a; b++){ //회전수 감소, 역삼각형 만들기 참고.
if(su[b] < su[b+1]){ //값 두개 비교, 만약 앞의 값이 뒤의 값보다 크다면,
tmp = su[b+1]; //큰 값(su[b+1])을 tmp변수에 대입
su[b+1]=su[b]; //su[b+1]위치에 작은값(su[b])을 대입
su[b]=tmp; //작은 값 위치에 tmp에 있던 값 대입
}//swap
}//for end
}//for end
for(int a = 0; a<su.length; a++){
System.out.print(su[a]+" ");
}
//결과값
//9 7 5 3 1
▶ 풀이
1) 선택정렬로 오름차순 정렬
정렬은 기준값과 그 다음차례 오는 값들을 비교하면서 순서를 정리하는 과정이다.
su라는 배열의 9 7 5 3 1을 오름차순 (작은것 -> 큰것) 으로 정렬해야한다.
1. for문을 작성해
기준이 될 순번이 될 정수 a를 0으로 선언하고 (기준은 총 갯수 -1) a의 범위는 su.length-1, 1씩 증가한다.
2. 그 안의 for문은 기준과 비교할 값의 순번이 늘어나는 문장인데 b번째의 값은
a번째의 값과 비교해야(그래서 a의 다음값부터)하므로 b=a+1으로 초기값을 정해준다.
범위는 <su.length; 로 끝까지 정해주고 1씩 증가한다.
3. if 조건문을 만들어주는데
3-1. 배열su의 a번째값과 b번째값과 비교해서 a번째 값이 크다면
3-2. swap을 위해 만든 변수 tmp에 작은 값인 b번째 값을 담아준다.
3-3. b번째 값(그릇)에 아까 비교해서 큰 값이 a번째 값을 넣어준다 <- 큰 값이 뒤로 밀린 것이다.
3-4. 큰 값이 있던 a번째 값(그릇)에 변수 tmp의 값을 넣어준다 <- 작은 값이 앞으로 온 것이다.
4. 위 조건을 배열의 갯수(길이) 만큼 반복한다.
5. for문으로 정렬된 배열의 원소들을 순서대로 출력한다.
2) 버블정렬로 내림차순 정렬
버블정렬은 양옆의 값들을 비교하며 정렬하는 것이다.
*회전수 감소, 역삼각형 만들기를 참고
1. for문의 a의 값을 3 (0 1 2 3 4인 배열이다 기준값인 a가 마지막 번호-1이므로 그래서 3이됨 )으로 정해주고
범위는 a는 0과 같거나 크다. a는 1씩 감소한다. (내림차순 만들어주기)
2. 그 안의 for문 b의 값은 0으로 b의 범위는 a와 같거나 작다. b는 1씩 증가한다. <- 이게 기준값
3. if 조건문을 만들어주는데
3-1. b번째 값과 b+1번째(기준 값의 다음 차례값)을 비교해서 b+1가 b보다 크다면
3-2. swap을 위해 만든 변수 tmp에 큰 값인 b+1번째 값을 담아준다.
3-3. b+1번째 값에 b의 값을 담아준다.
3-4. b의 값에 tmp의 값을 담아준다.
4. 위 조건을 배열의 갯수(길이) 만큼 반복한다.
5. for문으로 정렬된 배열의 원소들을 순서대로 출력한다.
sort 함수도 있음.
함수명이 같은데 여러개 있다 -> 오버로딩
매개변수와 자료형이 다르면 오버로딩이 가능하다.
import로 경로를 연결하는 것이다.
사용하고자 하는 클래스의 패키지 선언하는 것인데
import는 Ctrl + Space로 불러오면 자동 코딩된다.
package oop0528; //.java 파일에서 한번만 선언한다.
import java.util.*; //*자리에는 사용하고자 하는 클래스의 패키지 선언
import java.io.*;
import java.sql.*;
Arrays 클래스를 이용하여 오름차순 정렬하기.
//Arrays클래스를 이용해서 오름차순 정렬하기.
Arrays.sort(su); //ascending sort
for(int a = 0; a<su.length; a++){
System.out.print(su[a]+" ");
}
지난 주 과제 중
문제4) 로또 추첨기 1~45사이 중에서 서로 겹치지 않게 번호 출력하기.
등수
if( 자신 < ) { rank+1} // 등수 알고리즘 옆에 있는 애가 나보다 크면 나는 등수가 +1만큼 밀려난다.
정렬 오름차순
if( 자신 > ) { swap } //내가 옆에 있는 애보다 크면 자리 바꾸기.
로또번호
if( 자신 == ) { random() 다시 발생 } //값이 같을 때 다시 하기.
로또번호의 비교
3
3 5 (3과 5비교 //1번) 1
3 5 7 (3과 7비교 //1번, 5와 7비교 //2번) 2
3 5 7 9 (3과 9비교 //1번, 5와 9비교//2번, 7과 9비교//3번) 3
3 5 7 9 11 (3과 11비교 //1번, 5와 11비교//2번, 7과 11비교//3번 9와 11비교 //4번) 4
3 5 7 9 11 13 (3과 13비교 //1번, 5와 13비교//2번, 7과 13비교//3번 9와 13비교 //4번 11과 13비교 //5번) 5
....
총 숫자가 6개라면 6 - 1번 비교하게 된다.
총 수 = n , 비교 횟수 = n-1
회전수 증가 / 삼각형만들기와 형식이 비슷하다.
a=0 b=0 0<0
a=1 b=0 0<1
if(lotto[1] == lotto[0])
a=2 b=0 0<2
if(lotto[2] == lotto[0])
1 == 3
if(lotto[2] == lotto[1])
3 == 5
a=3 b=0 0<1
if(lotto[3] == lotto[0])
5 == 3
if(lotto[3] == lotto[1])
5 == 5 <- 값이 같기 때문에 break를 거는 것.
if(lotto[3] == lotto[2])
5 == 7
3번째 요소를 다시 돌리기.
break로 안에 있는 것 빠져나오는 것.
1보 후퇴했다가 다시 실행
■ 선생님 답안 ■
// 문제 4)
// 로또 추첨기 1-45 / 배열로 받아와서 겹치면 다시
int lotto[] = new int[6];
int size = lotto.length;
for(int i=0; i<size; i++){
lotto[i]=(int)((Math.random()*45)+1);
for(int j=0; j<i; j++){
if(lotto[i]==lotto[j]){
i--;
break;
}//if end
}//for end
}//for end
Arrays.sort(lotto); //ascending sort
for(int i=0; i<size; i++){
System.out.print(lotto[i]+" ");
}
랜덤값이 나왔을 때 그전에 나온 값과 같은 값이면 그 회차는 무효로 하고 다시 뽑는 것이다.
지난 주 과제 중
문제7) 10진수를 2진수로 변환하기.
지폐갯수 구하는 것과 비슷한 과정
// 문제 7) 10진수값을 2진수값으로 변환 후 // 출력하시오.
int num = 5;
int[] binary = new int[8];
int count = 0;
//1101 for문으로 2를 계속 나누어서 몫이 있으면 1, 없으면 0 그리고 나머지
while(true){ //무한 loop
binary[count] = num%2;
count++;
num = num/2;
if(num==1){
binary[count]=num;
break;
}
}//while end
for(int i=count; i>=0; i--){
System.out.print(binary[i]);
}
Interger 클래스를 활용한 수의 변환
//Integer 클래스를 활용한 수의 변환
System.out.println(Integer.toBinaryString(15));
System.out.println(Integer.toOctalString(15));
System.out.println(Integer.toHexString(15));
//결과값
//1111
//17
//f
4. 힙 정렬
5. 퀵 정렬
6. 쉘 정렬
'Backend' 카테고리의 다른 글
05월 30일 목 | OOP 11 - JAVA의 this(), Static, Final, String (0) | 2019.05.30 |
---|---|
05월 29일 수 | OOP 10 - JAVA의 Class와 접근제한자 (0) | 2019.05.29 |
05월 23일 목 | OOP 08 - JAVA의 Method (0) | 2019.05.23 |
05월 22일 수 | OOP 07 - JAVA의 배열 (0) | 2019.05.22 |
05월 21일 화 | OOP 06 - JAVA의 반복문(while)과 연습문제 (0) | 2019.05.21 |
댓글