2016년 4월 27일 수요일

기초적인 정렬알고리즘(4) - 선택, 버블, 삽입정렬 비교분석

앞서 선택, 버블, 삽입정렬의 특징들을 알아보았다.
이 3가지 정렬을 안다고해서 그냥 지나가듯 마무리 짓기엔 너무 아깝다는 생각이든다.
우리가 언제 어느상황에서 더 효율적으로 이 3가지의 정렬들을 사용할 수 있을까?
그러면 먼저 이 세 가지의 수행시간 분석도를 짚고 넘어가보자.


위의 세가지 수행시간인 최악, 평균, 최선으로 분류할 수 있다. 
이러한 경우의 조건은 우리가 정렬하고자 하는 값들이 이미 정렬이 되어있을때로 가정을 해보면 이해하기 쉬울것이다.

이미 정렬이 되어있는 상태에서 선택과 버블정렬은 의미없는 수행을 반복하지않겠는가?
버블정렬 같은경우에 특정 코드를 삽입해서 이미정렬되어있다는 것을 알려줄 수 잇으나
그러려면 메모리가 하나 더 추가가 되어있어야 하므로 효율적이지 못한 결과가 나온다.
반면에 삽입정렬은 처음 과정부터 n까지 앞뒤의 크기비교를 바탕으로 시작이되므로, 
Theta(n)의 시간이 걸리게 된다.

우리가 정렬을 배웠으면 단순한 원리를 알기보다는 어떠한 상황에서 더 효율적인 방법을 찾을 수 있을지 잘 기억해두자!

2016년 4월 20일 수요일

기초적인 정렬알고리즘(3) - 삽입정렬

선택정렬, 버블정렬을 배웠고 그 다음으로 배우게되는 삽입정렬은 이전에 배운 선택,
버블정렬의 수행시간보다 훨씬 빠른 시간안에 정렬이 될 가능성이 높다.
그럼 한번 알아보자!

선택, 버블정렬은 가장 큰 값을 뒤로보낸다는 목적이 서로 비슷했었다. 이와 다르게 삽입정렬은 두번째 기준 원소부터 시작해서 3,4 ,5 ... N번째 를 기준으로 정렬이 이루어진다.
그리고 이 기준값보다 앞에있는 값들을 미리 정렬을 시켜주면서 N번째까지 정렬이 이루어 지며  정렬을 할때 그 기준값에 맞춰서 정렬이 된 곳에 삽입해주므로 삽입정렬이라고 하는의미를 잘 기억해두자.

쉽게 말해서 "비교할 원소는 정렬된 곳에 삽입하며 정렬이 이루어진다." 라고 말할 수 있다.
예를들어 보자...

삽입정렬 - 오름차순
A[6] = { 4, 5, 3, 8, 2, 7 }

1회 과정 
4, 5, 3, 8, 2, 7   =>  2번째 위치한 기준값 '5'를 그 앞들의 숫자들과 비교.   5 3 8 2 7가
된다.
    
2회 과정
4, 5, 3, 8, 2, 7   =>  3번째 위치한 기준값 '3'을 앞의 숫자 5와 비교해보면 3이  5보다 작고 4보다 작은 위치이므로 4 앞에 위치하면 되는것이다. 그래서 3 4 5 8 2 7 이 된다.

이런식으로 (정렬된)앞의 숫자들을 비교하며 기준원소는 알맞은 위치에 들어가면되므로,
다음과 같은 결과가 나온다.

3회 과정   :   3, 4, 5, 8, 2, 7  => 3 4 5 8 2 7
4회 과정   :   3, 4, 5, 8, 2, 7  => 2 3 4 5 8 7
5회 과정   :   2, 3, 4, 5, 8, 7  => 2 3 4 5 7 8   => 정렬 완료.

이 과정들을 보면 두번째 값을 기준원소로 시작으로 N까지의 기준을 정하는 루프와 앞의 정렬된 숫자들과의 비교를 하는 루프구조가 필요하다는것을 짐작할 수 있을것이다. 이러한 루프의 수행시간은 큰 값을 찾는경우(선택정렬)나 앞뒤 하나씩 끝까지 비교하는(버블정렬)과 비슷한 시간으로 Theta(n의 제곱)의 수행시간이 걸릴것이다.

알고리즘을 살펴보면,



▶실행결과


기초적인 정렬알고리즘(2) - 버블정렬

기초적인 정렬 알고리즘 두번째는 버블정렬에 대하여 소개하겠습니다.

버블정렬(Bubble Sort) -오름차순 기준

버블정렬은 "큰 것들을 미리 뒤로 보낼래요"라고 생각하면 된다. 먼저, A[0~N]배열이
있다 가정해보자. A[N]까지 정렬이 이뤄지기 위해서는 A[0] A[1]비교, A[1] A[2] 비교부터
....A[N-1] A[N]까지의 비교를 통해서 큰 값이 뒤로가는 형태로 정렬이 된다.  
만약, A[0]과 A[1]을 비교 후 큰값이 나오는것을 뒤로 보내면된다.  그리고 그 큰값은 A[2]와 비교하고 또 여기서나온 큰값은 N개 까지 이어갈 것 이다. 조금 더 구체적으로 살펴보면,
6개의 정렬이 되지않은 배열이 있다 생각해보자.
A[6] = { 4, 9, 7, 2, 5, 3 };  
1회과정..
4 9 7 2 5 3  => 9는 4보다 이미크다. 즉, 자리교환이없다. ( A[0], A[1] 비교 )
4 9 7 2 5 3  => 9는 7보다 크다 즉, 자리교환실행 ( A[1], A[2] 비교 )
4 7 9 2 5 3  => 자리교환 ( A[1], A[2] 자리 교환)
4 7 9 2 5 3  => 9는 2보다 크다. 즉, 자리교환실행 ( A[2], A[3]비교 ) 
4 7 2 9 5 3  => 자리교환 ( A[2], A[3] 자리 교환)
4 7 2 9 5 3  => 9는 5보다 크다. 즉, 자리교환실행 ( A[3], A[4] 비교 )
4 7 2 5 9 3  => 자리교환( A[3]과 A[4] 자리 교환)
4 7 2 5 9 3  => 9는 3보다 크다. 즉, 자리교환실행 ( A[4], A[5] 비교 )
4 7 2 5 3 9  => 최종결과.

우리가 1회 과정만을 살펴봤을때 간단한 특징이 있다. 바로 맨 끝에 가장 큰 값이 들어가는것이다. 그럼 그 다음은 2번째로 큰수가 맨뒤 앞에 올것이다.  
이런식으로 정렬이 진행된다면....

2회 과정 => 4 2 5 3 7 9
3회 과정 => 2 4 3 5 7 9
4회 과정 => 2 3 4 5 7 9
5회 과정 => 2 3 4 5 7 9  >> 정렬이 완성된다.
이 과정들을 보면 가장 큰 값은 N번, N-1번, N-2번 ... 3번 2번까지의 순서로 쌓이게 된다.
(2번에 큰값이 온다는것은 마지막 1번과의 비교가 있었으므로 2번에서 마무리가 됨.) 
마지막 과정의 정렬까지 이루어지기 위해서는 에서는 N개, N-1개, N-2의 비교가 필요하고,
그 비교들은 배열의 총 갯수 N개에 비례. 즉, 배열의 갯수에 수행시간이 영향을 받는다는 것을 알 수 있다.  그리고 이 수행시간은 Theta(N제곱)이 되는 것 이다.

하지만 자세히 보면 4회 과정에서는 이미 정렬이 끝낸상태이다. 그럼에도 불구하고 4, 5회 까지의 과정들을 진행한다. 만약에 우리가 이미 정렬이 끝낸상태가 되었을때, 종료하는
방법은 없을까? 물론있다! 단 하나의 과정만 표시하면된다. 
바로 흔적을 남기는것이다. 우리가 각 회 과정을 보면 큰값이 뒤로가는 형태, 즉 하나의 값이라도 움직인다면 표시를 해둔다. 어떻게 하느냐? 생각해보면 "아차!" 할 것이다.
하나의 값이라도 움직인다 라는말은 "큰값이 앞에있다" 즉, "정렬을 하는중이다" 라고 생각하면 된다. 정렬이 마무리가 되지 않았기 때문이다. 반대로 정렬이된 상태라면 움직임이
없을것이다. 그럼 우리가 표시를 안하게 되고 그 표시가 안되어있으면
"어? 움직임이 없는걸보니깐 이미 정렬된상태구나!" 라고 생각해두면 훨씬 수월할것이다.
결국 3회의 과정에서 끝나므로 더 효과적인 버블정렬이 완성되는 것이다.

알고리즘을 알아보자!

<tok는 위에서 말했던 이미 정렬이 되었을경우 프로그램을 종료시키는 장치>


▶ 장치를 추가하기 전의 버블정렬 결과











▶ 장치를 추가한 후의 버블정렬 결과

2016년 4월 16일 토요일

기초적인 정렬알고리즘(1) - 선택정렬



 우리가 '물건을 구매할때 가격순으로 보는것'이나 '사전에서 찾고자하는 단어를 찾을 때' 의 상황들처럼 수 많은 정보들 중에서 원하는 정보만 뽑아 볼 수 있다.

 이처럼 정보들을 나열하는것을 정렬(sort)이라고 하는데, 다양한 종류의 정렬중 선택정렬에 대해서 알아가보자.

 선택정렬(Selection Sort) - 오름차순 기준
선택정렬은 가장 큰 값을 뒤로보내고, 그다음 두번째 큰값을 뒤로보내는 식으로 쌓여가는 형태로 정렬이되는 것이다. 먼저, 앞에서부터 n(데이터크기)까지 비교를 통해 가장 큰 값(MAX)를 찾은 뒤, 그 큰 원소가 위치하는 자리와 맨 뒷 자리 원소의 자리를 바꾸어주면 된다. 그리고 그 다음부터 1부터 n-1에서 MAX값을 구해서 n-1번째 위치를 교환을 통해서
정렬이 이루어진다.

ex.  3 2 6 3 4 3 1 이 있는경우 가장 큰 원소는 6이다. 6을 맨 뒤 1이 위치한 자리와 바꾸면
3 2 1 3 4 3 6 가 된다. 이게 첫번째 과정이다.  이 과정들을 반복해보면..
3 2 1 3 3 4  - 2회 
3 2 1 3 3 4 6  - 3회
3 2 1 3 3 4 6  - 4회
1 2 3 3 3 4 6  - 5회
1 2 3 3 3 4 6  - 6회 
위 과정들을 통해서 정렬이 된다는것을 알 수 있다. 여기서 우리는 수행시간에 대해서 알아보자. 먼저 1부터 6까지 MAX값을 구하는 방법 즉, 비교는 n개의 크기에서 n-1회 그다음 
n-2 이렇게 계속 작아지므로 n-1번의 비교가 필요하다. 이것은 크기에 비례가 된다.
그리고 맨뒤에 보내지는 과정들 맨 끝 n부터 2가 될 때까지 반복한다. 그러므로 수를 비교하는 총 횟수는 (n-1)+(n-2)+... +2+1=n(n-1)/2, 즉Theta(n제곱)의 수행시간이 걸릴것이다.
수행시간에서 수학적으로 접근하기보다는 어느 상황에서의 수행시간에 영향을 미치는지에 대해서 알아두길 바란다. 
여기서는 수를 비교하는 횟수가 전체 시간을 좌우한다.

알고리즘을 살펴보면,



▶실행결과






알고리즘 개요


알고리즘을 배우는 이유는 더 나은 프로그래밍 실력도 쌓을 수 있는 기회가
되지만 그것보다 더 나은 프로그래밍을 완성하기 위해서 알아가면 좋을것이다.

 같은 프로그램을 구현하더라도 그 안에 내용들은 사람마다 다를것이다. 
ex) 수행시간, 코드의 길이 등 

 오래걸리고 소스코드의 내용이 길고 복잡한 프로그램보다는
수행시간이 줄어들고 또 코드의 길이도 짧은 프로그램, 또 어떻게보면 더 단순해보일 수
도 있는 그런 효율적인 프로그램을 만들어가기 위해서 알고리즘을 배우는것은 당연하다.



2016년 4월 6일 수요일

프로세스(Processs)와 스레드(Thread)






 스레드란?
 먼저, 스레드는 컴퓨터 프로그램 실행시 프로세스 내부에 존재하는 수행경로이다.
하나의 프로세스에서 둘 이상의 흐름을 만들때 사용이되며, 프로세스 생성시 하나의 
주 스레드가 실행이되어 대부분의 작업을 처리하고 주 스레드가 종료되면 프로세스도 종료
된다.


* 멀티태스킹 : 하나의 운영체계에서 둘 이상의 프로세스가 동시에 실행되는 환경.
* 멀티스레딩 : 하나의 프로세스에서 다수의 스레드가 동시에 수행되는 것.


[Java] N-I/O(Non-Blocking) 파일 읽기 쓰기 - GatheringByteChannel, ScatteringByteChannel, ByteBuffer 사용.

우리는 지금까지 다음과 같이 살펴보았다. 1.  InputStream / OutputStream : 입, 출력 스트림을 바이트로 처리하여 읽기, 쓰기. 2.  FileInputStream / FileOutputStream : 입, 출력 스트림을 ...