본문 바로가기

[그린컴퓨터] Server/Algorithm

알고리즘 { 개요, 순서도, 연습문제 }

728x90

알고리즘은 일종의 방법론이라고 할 수 있다. 프로그램이 간단하다면 방법론은 필요 없지만 프로그램이 복잡해짐에 따라 쉽게 해결하기 위해서 방법론이 필요해졌다. 대표적인 방법론으로는 알고리즘과 애자일이 있는데, 이번에 배워볼 것은 알고리즘이다. 

 

어떠한 문제가 있을 때 문제는 복잡하게 꼬여있어 보여서 풀기가 어렵다. 이런 문제를 내가 해결할 수 있는 작은 단위로 먼저 쪼개고 그 문제들을 순차 & 선택 & 반복 구조를 활용해서 해결해나가는 것이 알고리즘이라고 할 수 있다. 

알고리즘은 문제를 해결하는 과정을 글이나 그림으로 표현할 수 있다. 순서도는 알고리즘을 그림으로 표현한 것을 의미한다. 순서도를 작성할 때는 여러 가지 기호를 사용하게 된다. 순서도를 위에서부터 아래 방향으로 배치를 해서 작성하게 된다. 제일 위에 프로그램의 시작 제일 아래에 있는 것이 프로그램의 종료이다. 그 사이에 변수 선언, 데이터 입출력, 명령 처리, 반복문과 조건문의 분기문으로 프로그램의 순서를 정리하는 것이 순서도입니다.

순서도를 작성하는 방법은 3가지 단계로 구성됩니다.

 

1. 문제 이해

변수의 용도를 파악하는 것이 우선 시행되어야 합니다. 예를 들어서 변수 x 가 결과를 저장하는데, 그냥 x 가 있네가 아니라 프로그램의 결과를 저장하기 위한 x 구나 하고 이해해야 한다. 

 

2. 제어 구조 선택

주어진 조건과 반복 횟수를 파악하여 제어 구조를 선택하고 구성한다. 예를 들어 스캐너 클래스로 문자를 입력 받다가 특정 문자가 들어오면 종료한다고 하면 반복 횟수는 정해지지 않았으니 무한루프이고 특정 문자가 조건이 된다. 이런 식으로 제어 구조를 파악하는 것이다. 

 

3. 로직 구성

필요한 요소들을 파악했다면  수행 순서를 정리해 주는 것이 로직 구성이다. 


이런 구성과 순서를 그림으로 표현한 것이 순서도입니다. 알고리즘에서 중요한 것은 어려운 문제를 만났을 때 무작정 코드를 작성하는 것이 비효율적임을 이해하는 것입니다. 

산술연산 로직
package main;

public class Ex1 {
//	산술연산
//	Q. 10 + 5 * 4 의 결과를 변수 x 에 저장하라. 
	public static void main(String[] args) {
		int x;
		x = 10 + 5 * 4; // x 에 연산한 결과를 저장한다. 
	}

}​

 

위 문제는 간단한데, 문제를 읽어보고 필요한 변수를 설정한 다음 변수가 어떤 변수인지 설명을 적어 놓는 것. 이 과정이 중요하다. 왜냐하면 변수(멤버)를 정의하면 그 변수를 어떻게 사용할지 로직을 자연스럽게 구현하게 된다. 

입출력과 산술 연산

package main;

import java.util.Scanner;

// Q. 변수 x 에 정수를 입력 받고, x + 5 를 연산해 변수 y에 저장한다.
public class Ex2 {

	public static void main(String[] args) {
		int x; // x는 정수를 저장하기 위한 변수이다
		int y; // y는 결과를 저장하기 위한 변수이다
		
		Scanner scanner = new Scanner(System.in);
		
		x = scanner.nextInt();
		y = x + 5;
		System.out.println(y);
	}
}

대단한 프로그램은 아니지만 결국 습관을 만드는 것이 중요하다. 즉, 멤버들이 어떤 역할과 목표를 가지고 설정되었는지를 작성을 한 이후에 코드로 변환하는 작업을 진행하면 훨씬 효율적으로 작업을 진행할 수 있다. 

연습문제 1
package quiz;

// 변수 x 을 선언하고 25 대입
//변수 y 를 선언하고 40 대입 
//두 변수 갑 바꾸기
public class Quiz1 {
	
	public static void main(String[] args) {
		int x; // x는 25를 대입 받는 변수
		int y; // y는 40을 대입 받는 변수
		int mediator; // mediator는 값을 바꿀 때 값을 받는 변수
		
		x = 25;
		y = 40;
		mediator = x;
		x = y;
		y = mediator;
		
		System.out.println(x);
		System.out.println(y);
	}

}​
변수(멤버)를 먼저 선언한 이후 변수(멤버)를 설명을 하고 설명을 토대로 로직을 구성했다. 

예제 3번. 
package main;

import java.util.Scanner;

// Q. 변수 score에 정수를 입력 받고, score 가 70점 이상인가를 판별하여 출력한다
public class Ex3 {
	public static void main(String[] args) {
		int score; // score는 정수를 저장하기 위한 변수이다
		
		Scanner scanner = new Scanner(System.in);
		score = scanner.nextInt(); // 정수를 입력받아 score 에 저장한다. 
		
		if (score >= 70) {
			System.out.println("합격입니다.");
		} else {
			System.out.println("불합격입니다.");
		}
	}
}​
변수 score 에 정수를 입력 받고 score 가 70점 이상인가를 판별하여 메시지를 출력합니다. 마찬가지로 문제를 인식하고 변수(멤버)를 정의한 후 로직을 구성했습니다. 
연습문제 2
package quiz;

import java.util.Scanner;

// Q. Scanner 클래스를 사용하여 두 숫자를 입력 받는다. 
// 첫 번째 숫자가 두 번째 숫자로 나누어 떨어지는지 확인 한다.
// 결과에 따라 '나누어 떨어짐' '나누어떨어지지않음' 을 출력한다. 
public class Quiz2 {

	public static void main(String[] args) {
		int i1;  // 입력 받을 첫 번째 수
		int i2;  // 입력 받을 두 번째 수
		
		Scanner scanner = new Scanner(System.in);
		System.out.println("첫 번째 수 입력");
		i1 = scanner.nextInt();
		System.out.println("두 번째 수 입력");
		i2 = scanner.nextInt();
		
		if (i1 % i2 == 0) {
			System.out.println("나누어 떨어진다");
		} else {
			System.out.println("나누어 떨어지지 않는다.");
		}
	}
}​
조건문이 필요한 경우도 마찬가지이다. 
연습문제 3
package quiz;

import java.util.Scanner;

// Scanner 클래스를 사용하여 숫자 3개를 입력 받는다
// 세 개 중 가장 큰 값을 구한다. 
public class Quiz3 {
	public static void main(String[] args) {
		int[] arr = new int[3];  // 입력 받은 숫자를 저장하는 배열 
		int largerInt = 0; // 배열에서 큰 값을 저장하는 변수
		Scanner scanner = new Scanner(System.in);
		for (int i = 0; i < arr.length; i++) {
			System.out.println(i+1 + "번 째 숫자를 입력하세요.");;
			arr[i] = scanner.nextInt();
		}
		for (int i = 0; i < arr.length-1; i++) {
			largerInt = arr[0];
			if (arr[i] < largerInt) {
				continue;
			} else {
				largerInt = arr[i];
			}
		}
		System.out.println("입력된 값 중 가장 큰 값은 " + largerInt + "입니다." );
	}
}
변수 3개를 사용해서 입력 값을 배정할 수도 있는데, 변수가 많아질 수록 복잡해질 테니까 배열로 처리했다. 문제를 보면 '찾는다' 혹은 '구한다' 라는 문구가 사용되었다. 이런 문제를 해결할 때는 무조건 비교 연산자를 사용하게 된다. 
예제 4. 반복문
package main;

// <반복문>
// 정수 1 부터 10까지 모두 합하여 결과를 출력한다.
public class Ex4 {
	public static void main(String[] args) {
		int i; // i 는 반복문의 조건으로 사용하기 위한 변수이다.
		int sum = 0; // sum은 결과를 저장하기 위한 변수이다. 
		
		// i가 1부터 10이 될 때까지 10번 반복된다. 
		for(i=1; i<=10; i++) {
			sum = sum + i; // sum 에 i 를 더한다. 
		}
		
		System.out.println(sum); // sum 을 출력한다.
	}
}​
반복문은 그림으로 살펴보겠습니다. 
시작, 변수 선언, 명령처리, 반복문 + 명령처리, 데이터 입출력, 종료
예제5. 함수
package main;

import java.util.Scanner;

// 함수 예제
public class Ex5 {

	public static void add(int n1, int n2) { // 함수 정의 
		int sum; // sum 은 결과를 저장하기 위한 변수이다
		sum = n1 + n2;
		System.out.println(sum);
	}
	
	public static void main(String[] args) {
		int num1; // num1, num2 는 정수를 저장하기 위한 변수이다. 
		int num2;
		
		Scanner scanner = new Scanner(System.in);
		num1 = scanner.nextInt();  // 정수를 입력받아 num1 에 저장한다
		num2 = scanner.nextInt();  // 정수를 입력받아 num2 에 저장한다
		
		add(num1, num2);
	}

}​
함수를 사용할 때는 함수를 선언하는 부분과 함수를 사용하는 부분을 주의깊게 보아야 한다. 순서도를 살펴보면 프로그램 시작 단계에서 add 함수를 정의하였다. 그 이후 필요한 멤버 변수를 정의했고, 명령 처리, 출력, 종료로 순서도가 구성되는 것을 볼 수 있다. 

함수를 선언할 때는 함수 이름을 카멜 케이스로 작성을 하고, 입력 값이 필요한 함수면 매개변수를 선언해야 한다. 결과를 반환해야 하는 함수면 리턴 타입을 함께 선언한다. 
함수를 호출할 때는 호출 하는 함수의 특징에 따라 매개변수를 같이 전달하여 호출한다. 
연습문제4 함수
package quiz;

import java.util.ArrayList;

// getSum 함수는 배열에 저장된 모든 숫자의 합을 계산하여 반환합니다
// 메인 함수에서는 배열을 생성하고, getSum 함수를 호출하여 합계를 계산하고 출력합니다. 
public class Quiz4 {

	public static void main(String[] args) {
		ArrayList<Integer> arr = new ArrayList<Integer>();
		arr.add(10);
		arr.add(20);
		arr.add(30);
		arr.add(40);
		getSum(arr);
	}
	
	public static void getSum(ArrayList<Integer> arr) {
		int sum = 0; // 배열의 숫자 합을 저장할 변수
		for (int i = 0; i < arr.size(); i++) {
			sum = sum + arr.get(i);
		}
		System.out.println(sum);
	}
}​
Arraylist 를 사용했는데, 문득 Arraylist 를 List 로 어떻게 바꾸는지 궁금해서 구글에 물어봤더니, Arraylist 와 기본 배열은 서로 교환을 가능하게 해주는 클래스들이 있었다. 제약사항이 없는 것은 아닌 것 같다. 아무튼 함수에서 매개변수를 사용할 때 생각해야 할 점이 하나 있는데, 매개변수는 실제로 값을 가져가는 것이 아니라 메모리 값을 복사해 가져간다는 점이다. 
연습문제 5 . reverse
첫 번째 방법
package quiz;

//reverse 함수는 문자열을 거꾸로 출력합니다. 
public class Quiz5 {

	public static void main(String[] args) {
		String str = "안녕하세요";
		reverse(str);
	}
	
	public static void reverse(String str) {
		for (int i = str.length()-1; i >= 0; i--) {
			System.out.println(str.charAt(i) + " ");
		}
	}
}​
첫 번째 방법은 String 자료형의 charAt( ) 메서드를 활용하는 방법이다. 코드가 훨씬 간단한 것을 볼 수 있다. 

두 번째 방법
package quiz;

// reverse 함수는 문자열을 거꾸로 출력합니다. 
public class Quiz5 {

	public static void main(String[] args) {
		char[] arr = {'안', '녕', '하', '세', '요'};
		reverse(arr);
	}
	
	public static void reverse(char[] arr) {
		char[] newarr = new char[5]; // arr 을 반대 순서로 받을 새로운 배열
		for (int i = 0, j = arr.length-1; i < arr.length; i++,j--) {
				newarr[j] = arr[i];
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.println(newarr[i]);
		}
	}
}​
두 번째 방법은 String 의 기본 형태인 char[ ] 을 직접 만들어서 직접 구현하는 방법이다. 코드가 같은 동작을 하는데도 조금 더 복잡해 보인다. 
예제6. 기본배열
package main;

// 크기가 3인 배열을 생성하고 1, 2, 3 을 저장한다. 
// 그리고 배열의 두 번째 요소를 출력한다. 
public class Ex6 {

	public static void main(String[] args) {
		int arr[] = new int[3]; // arr 은 기본 배열로 크기가 정해진 배열이다. 
		
		arr[0] = 1;
		arr[1] = 2;
		arr[2] = 3;
		
		System.out.println(arr[1]);
	}

}​
기본 배열과 arraylist 의 차이를 볼 수 있는 예제다.
연습문제6. 기본배열과 반복문 
package quiz;

import java.util.Scanner;

// 크기가 5인 배열을 생성한다
// Scanner 클래스를 사용하여 배열에 숫자 5개를 입력받는다
// 배열에 저장된 모든 숫자의 합을 구한다 
public class Quiz6 {

	public static void main(String[] args) {
		int[] arr = new int[5];
		Scanner scanner = new Scanner(System.in); // 사용자 입력을 받은 scanner 객체
		int sum = 0; // 배열의 합을 저장할 변수 
		
		for (int i = 0; i < arr.length; i++) {
			int x = scanner.nextInt(); // x 변수는 사용자 입력값을 받는다.
			arr[i] = x; // x 변수의 값을 배열에 넣어준다. 
			sum = sum + x; // sum 에 x 를 더한다. 
		}
		
		System.out.println(sum);
	}
}​
연습문제7. 배열과 동적처리
package quiz;

// 크기가 5인 배열에 10, 5, 1, 30, 15 를 저장한다
// 그리고 값 15가 저장된 위치를 찾는다. 
// 단 동적으로 처리 가능하도록 구현한다.
public class Quiz7 {

	public static void main(String[] args) {
		int[] arr = {10, 5, 1, 30, 15};
		int x = 15; // 찾고자 하는 값을 x 변수에 담는다. 
		
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] == x) {
				System.out.println(x + "는 " + i + "번 째에 있습니다.");
				break;
			}
		}
	}
}​
변수 x 값에 따라 찾는 값을 손쉽게 바꿔줄  수 있다.
연습문제8. 기본배열과 조건문
package quiz;

// 크기가 5인 배열에 10, 5, 1, 30, 15 를 저장한다
// 가장 작은 값을 찾는다.
public class Quiz8 {
	public static void main(String[] args) {
		int[] arr = {10, 5, 1, 30, 15};
		int small = arr[0];
		
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] < small) {
				small = arr[i];
			}
		}
		
		System.out.println("배열의 가장 작은 값은 " + small + " 입니다.");
	}
}​

 

 

 



Calendar
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Visits
Today
Yesterday