이번 포스팅에서는 C# 선택정렬과 param 에 대해서 알아본다.
선택정렬은 기초적인 정렬 알고리즘이다. static 메소드로 만들 것이며 params 로 가변길이 매개변수를 받을 것이다.
참고로 아래 코드에는 선택 정렬이 일어나는 동안에 일어나는 동작을 뜯어 보기 위해서 삽입한 코드들이 있어서 가독성이 좋지 않다.
코드를 읽기 전에 개요 설명을 듣고 코드를 들여다 보는 것이 나을 것이다.
using System;
namespace CSharpBasic
{
class Program
{
static void Main(string[] args)
{
int[] array = Sort(5, 3, 7, 1, 9, 4, 8, 2, 6);
Console.WriteLine("After Sort");
foreach(int nb in array)
{
Console.Write(nb + ", ");
}
Console.WriteLine();
}
static int[] Sort (params int[] array)
{
Console.WriteLine("Before sort");
for (int l = 0; l < array.Length; l++)
{
Console.Write(array[l] + ", ");
}
Console.WriteLine();
for (int i = 0; i < array.Length-1; i++)
{
Console.WriteLine();
Console.WriteLine("index[{0}] : {1} ", i, array[i]);
for (int j = i+1; j < array.Length; j++)
{
Console.Write("([{0}]: {1}, [{2}]: {3}) ", i, array[i], j, array[j]);
if (array[i] > array[j])
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
Console.WriteLine();
for (int k=0; k<array.Length; k++)
{
Console.Write(array[k] + ", ");
}
Console.WriteLine();
}
Console.WriteLine("It's done");
Console.WriteLine();
return array;
}
}
}
params 는 매개변수의 개수를 늘리거나 줄일 수 있다. 아래와 같이 배열앞에 사용하면 가변 길이의 인수를 넣을 수 있다.
prams int[] 라고 선언하면 정수를 얼마를 넣건 매개변수를 정수 배열로 만들어서 사용하고 가변길이 배열로 돌려줄 수 있다.
static int[] Sort (params int[] array)
정렬을 하기 위한 데이터를 준비했다. 원하는 숫자 만큼 인수를 넘긴다. 1부터 9까지 숫자를 순서없이 함수의 parameter에 넣어준다.
int[] array = Sort(5, 3, 7, 1, 9, 4, 8, 2, 6);
맨위의 코드에서 군더더기를 제외하면 아래와 같다. 바깥쪽 for문과 안쪽 for 문을 사용하여 정렬할 수 있다.
static int[] Sort (params int[] array)
{
for (int i = 0; i < array.Length-1; i++)
{
Console.WriteLine("index[{0}] : {1} ", i, array[i]);
for (int j = i+1; j < array.Length; j++)
{
if (array[i] > array[j])
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
return array;
}
바깥쪽 루프가 처음 한번 돌게되면 배열의 첫번째 요소는 확실히 가장 작은 숫자가 오는 것을 보장한다.
5,3,7,1,9,4,8,2,6 숫자가 주어졌을 때 첫번째 루프는 아래와 같이 돌아간다.
if문을 보면 배열의 4번째 요소인 1이 나올 때까지 두번 값의 변경이 일어난다.
일단 가장 작은 값이이 배열의 제일 처음 array[0] 자리에 들어가면 그 다음 부터 마지막 요소까지 비교해봐도 if문은 False 를 리턴한다.
즉 자리는 확정되고 추가적인 변경이 일어나지 않는다. 이렇게 n-1 만큼의 바깥쪽 루프가 완료되면 배열은 오름차순으로 정렬된다.
i |
j |
array[i] |
array[j] |
if(array[i] > array[j]) |
temp |
array[i] |
array[j] |
0 |
1 |
array[0] = 5 |
array[1] = 3 |
True |
5 |
array[0] = 3 |
array[1] = 5 |
0 |
2 |
array[0] = 3 |
array[2] = 7 |
False |
5 |
array[0] = 3 |
array[2] = 7 |
0 |
3 |
array[0] = 3 |
array[3] = 1 |
True |
3 |
array[0] = 1 |
array[3] = 3 |
0 |
4 |
array[0] = 1 |
array[4] = 9 |
False |
3 |
array[0] = 1 |
array[4] = 9 |
0 |
5 |
array[0] = 1 |
array[5] = 4 |
False |
3 |
array[0] = 1 |
array[5] = 4 |
0 |
6 |
array[0] = 1 |
array[6] = 8 |
False |
3 |
array[0] = 1 |
array[6] = 8 |
0 |
7 |
array[0] = 1 |
array[7] = 2 |
False |
3 |
array[0] = 1 |
array[7] = 2 |
0 |
8 |
array[0] = 1 |
array[8] = 6 |
False |
3 |
array[0] = 1 |
array[8] = 6 |
정렬이 완료되었으면 foreach 문으로 콘솔에 출력한다. 배열에 정렬한 오름차순 순서대로 출력이 될 것이다.
static void Main(string[] args)
{
int[] array = Sort(5, 3, 7, 1, 9, 4, 8, 2, 6);
Console.WriteLine("After Sort");
foreach(int nb in array)
{
Console.Write(nb + ", ");
}
Console.WriteLine();
}
결과창에는 일부러 데이터의 정렬과정상 동작과정을 보기 위해서 중간중간 콘솔출력을 사용했다.
비주얼 스튜디오의 디버그 기능을 사용하면 세부적인 과정을 다 볼 수 있다.
중단점을 Sort 함수의 첫문장에 위치시키고 F5로 디버그 시작 후 F11로 한단계씩 실행할 수 있다.
알고리즘은 언어 공통이니까 보통 C계열에서 습득하면 다른 언어로 이식(? 좀 거창하게 들리지만) 하는 것은 어렵지 않다. 그보다 요즘은 컴파일러와 프레임워크가 제공하는 자료형과 정렬기능을 사용한다. 사용하기 쉽게 만들어 놨고 성능에 최적화 되어 있다. 괜히 프레임워크를 쓰는게 아니다.
알고리즘은 한번씩 리마인드 하는 정도로 보면 좋다. 재미가 있는 사람은 더 깊게 파고들어서 자신만의 알고리즘을 만들어 나갈 것이고, 있는 알고리즘을 응용하는 것만 해도 상당한 경지에 오른 것이다. Don't reinvent the wheel 수레바퀴를 재발명 하지 말라는 말과 Standing on the shoulders of giants 거인의 어깨에 올라 넓은 세상을 바라보라는 재미있는 말이 있다. 위키의 설명은 더 흥미롭다.
"Using the understanding gained by major thinkers who have gone before in order to make intellectual progress"
지성적 진보를 이루기 위해 지나간 주요 생각자( major thinker) 가 얻은 이해를 사용하라.
주요 생각자? 우리말로는 '현인' '성현' 정도의 단어가 떠오르지 않을까 싶다. 원문 그대로를 느껴보면 thinker 란 단어는 '생각하는 사람' 을 의미한다. 뭐 생각은 누구나 하고 사니까... 그런데 major thinker 는 생각하는 사람들이 다 해당되는게 아니라 주요한 사람들이다. 군대의 계급에 major는 소령에 해당한다. 즉 군대로 비유하면 일반 졸병들 장교도 아니라 소령이상의 계급에 위치한 사람 정도가 되야 된다는 것이다.
참고로 소령 다음이 중령인데 중령부터 약 3000명 정도의 연대장 급 위치이다. major thinker 라는 것은 생각하는 사람 3000명에 한 명정도에게 줄 수 있는 칭호인가 보다... 만 언제나 우리가 이야기하는 거인들은 그보다 더 넘사벽의 사람들이다.
살다보면 거인의 알고리즘을 이해하는 것도 응용하는 것도 결국 거인의 일이라는 것을 알게 된다. 공교육을 받아서 거기까지 가는 것은 거의 낮은 확률이다.
이 블로그는 잡담이 많다. 나중에 잡담만 뽑아내서 다른 글로 모으려고 해서 그렇다.