모름

선택정렬을 마스터하는 마지막 프로젝트입니다. 시각화의 조건은 아래와 같습니다.

 

1번부터 차례대로 풀어보도록 하겠습니다.

 

1. 배열에서 선택 정렬을 실행하는 코드를 만들어 보세요.

class Solution {
    static void Main(string[] args)
    {
        //////////////// 1. 배열에서 선택 정렬을 실행하는 코드를 만들어 보세요.
        //스왑함수가 필요합니다. (제일 작은 값을 스타트 인덱스 자리와 바꿔줘야하기때문에)
        //제일 작은 인덱스가 몇 번인지 알려주는 함수가 필요합니다.
        //마지막으로 선택정렬 함수를 만들어 정리해주면 끗
    }
}

우선 뭘 할지 대략 정리합니다.

 

    static void Swap(int[] array, int firstIndex, int secondIndex)
    {
        int tmp = array[firstIndex];
        array[firstIndex] = array[secondIndex];
        array[secondIndex] = tmp;
    }

이따 사용할 스왑 함수를 만들고

 

    static int IndexOfMinum(int[] array, int startIndex)
    {
        //제일 작은 값을 찾아서 최소 인덱스랑 교환시킵니다.
        int minNum = array[startIndex];
        int minIndex = startIndex;

        for (int i = startIndex+1; i < array.Length; i++)
        {
            if(array[i] < minNum)
            {
                minNum = array[i];
                minIndex = i;
            }
        }
        return minIndex;
    }

그리고 가장 작은값의 인덱스를 찾아주는 함수도 만듭니다.

 

    static void SelectionSort(int[] array)
    {
        int minIndex = 0;

        for (int i = 0; i < array.Length; i++)
        {
            minIndex = IndexOfMinum(array, i);
            Swap(array, i, minIndex);
        }
    }

위 함수를 이용해서 선택정렬 함수를 만들었습니다. 마지막으로 콘솔로 값을 입력받을 수 있게 입력함수와 출력함수를 만들어 보겠습니다.

 

    //(,)로 구분된 정수형 배열 입력
    static int[] ReadArray(string input)
    {
        string[] inputArray = input.Split(',');
        int[] array = new int[input.Length];

        for (int i = 0; i < inputArray.Length; i++)
        {
            array[i] = int.Parse(inputArray[i]);
        }

        return array;
    }
	
    //배열 출력
    static void WriteArray(int[] array)
    {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < array.Length; i++)
        {
            if (i == array.Length - 1) sb.Append(array[i]);
            else sb.Append(array[i]).Append(",");
        }

        Console.WriteLine(sb);
    }

입력받는 함수와 출력하는 함수를 만들었습니다. 마지막으로 메인에 선택정렬을 구현해보겠습니다.

 

    static void Main(string[] args)
    {
        int[] array = ReadArray(Console.ReadLine());
        SelectionSort(array);
        WriteArray(array);
    }

메인함수는 이렇게 깔끔하게 정리 할 수 있습니다.

 

정렬은 되고있습니다만 무슨 문제인지 앞에 0이 붙어 나옵니다. 배열의 길이가 다르게 나오는 걸로 보아, 배열을 입력받을 때 배열의 크기가 달라지지 않았나 생각해봅니다.

 

    static int[] ReadArray(string input)
    {
        string[] inputArray = input.Split(',');
        int[] array = new int[input.Length];

        for (int i = 0; i < inputArray.Length; i++)
        {
            array[i] = int.Parse(inputArray[i]);
        }

        return array;
    }

문제는 ReadArray함수에 있었습니다.

 

        string[] inputArray = input.Split(',');
        int[] array = new int[inputArray.Length];

기존에 int[] array = new int[input.Length] 로 되어있던 것을 inputArray.Length로 바꿔줬습니다. 기존에 입력받은 모든 값(string)의 배열길이를 받아왔기에 배열의 크기가 달라졌던 겁니다.

 

정상적으로 선택정렬하는 프로그램을 작성했습니다. [1. 배열에서 선택 정렬을 실행하는 코드를 만들어 보세요.]를 해결했습니다. 이제 2번 문제로 넘어가겠습니다.

 

2. 배열이 반복될 떄마다 배경에 배열 상태를 시각적으로 표시해야 합니다.

이번 단계에선 배열이 바꿔질때마다 배열 상태를 바꾸라는 의미입니다. 선택정렬 함수에서 스왑하고 나서 반복문이 돌아가기 직전에 배열을 출력하면 될것 같습니다.

 

    static void SelectionSort(int[] array)
    {
        int minIndex = 0;

        for (int i = 0; i < array.Length; i++)
        {
            minIndex = IndexOfMinum(array, i);
            Swap(array, i, minIndex);

            Console.Write("총 {0}번 반복: ", i);
            WriteArray(array);
        }
    }

선택정렬 함수에 배열을 출력하는 부분을 추가해줍니다.

 

            Console.Write("총 {0}번 반복: ", i);
            WriteArray(array);

자 이렇게 함으로서 배열이 한번씩 반복될때마다 전체 배열이 출력됩니다. 5개의 입력을 넣으면 총 5번 반복이 되야합니다. 테스트 해보겠습니다.

 

정상적으로 출력됩니다. 5개의 수를 입력받았고, 5번 반복하면서 달라지는 배열을 반복해서 출력했습니다. [2. 배열이 반복될 떄마다 배경에 배열 상태를 시각적으로 표시해야 합니다.] 정상적으로 2번 시각화를 해결했습니다.

 

3. 배경에 교체 연산이 적용된 숫자에 대한 시각적인 표시를 해야 합니다.

이번에는 교체된 숫자에 대해서 시각적인 표시를 해야합니다. 다행히 저희에게는 교체 연산이 적용된 숫자를 구하는 함수를 미리 만들었습니다. 바로 IndexOfMinum() 이었습니다. 이 부분을 수정해보겠습니다.

 

    static int IndexOfMinum(int[] array, int startIndex)
    {
        //제일 작은 값을 찾아서 최소 인덱스랑 교환시킵니다.
        int minNum = array[startIndex];
        int minIndex = startIndex;

        for (int i = startIndex+1; i < array.Length; i++)
        {
            if(array[i] < minNum)
            {
                minNum = array[i];
                minIndex = i;
            }
        }
        return minIndex;
    }

적용하려고 보니 minIndex를 정상적으로 리턴해주기 때문에 이 값을 가지고 출력부분에서 고치는게 좋을 것 같습니다.

 

    static void SelectionSort(int[] array)
    {
        int minIndex = 0;

        for (int i = 0; i < array.Length; i++)
        {
            minIndex = IndexOfMinum(array, i);
            Swap(array, i, minIndex);

            Console.Write("총 {0}번 반복: ", i);
            WriteArray(array, i);
        }
    }

우선 위 코드에서 스왑된 값인 [i]를 인자로 출력부분에서 받아와서 처리하겠습니다. 스왑된 값의 인덱스인 [i]는 교체연산이 적용된 숫자의 인덱스입니다.

 

    static void WriteArray(int[] array, int resultNum)
    {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < array.Length; i++)
        {
            if (resultNum == i && resultNum == array.Length - 1) sb.Append("[").Append(array[i]).Append("]");
            else if (resultNum == i) sb.Append("[").Append(array[i]).Append("]").Append(",");
            else if (i == array.Length - 1) sb.Append(array[i]);
            else sb.Append(array[i]).Append(",");
        }

        Console.WriteLine(sb);
    }

출력 함수에서 교체연산이 적용된 index를 인자로 받아와서 출력할때 조건문을 달아서 따로 표시해주겠습니다. 조금 지저분해보이지만 잘 동작합니다.

 

하지만 교체연산이 적용된 index는 교체되기 전 수도 가리키고 있어야합니다. 아래처럼요.

어떻게 하면 콘솔로 표현할 수 있을까요... 

이렇게 표현됐습니다. (num)이 교체되기 전 숫자를 의미하고 [num]이 교체된 숫자를 의미합니다. 

 

    static void WriteArray(int[] array, int resultIndex, int beforeIndex)
    {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < array.Length; i++)
        {
            if(resultIndex == -1)
            {
                if (beforeIndex == i) sb.Append("(").Append(array[i]).Append(")").Append(",");
                else sb.Append(array[i]).Append(",");
            }
            else if (resultIndex + 1 == array.Length-1)
            {
                if (resultIndex == i) sb.Append("[").Append(array[i]).Append("]").Append(",");
                else sb.Append(array[i]).Append(",");
            }
            else
            {
                if (resultIndex == i) sb.Append("[").Append(array[i]).Append("]").Append(",");
                else if (beforeIndex == i) sb.Append("(").Append(array[i]).Append(")").Append(",");
                else sb.Append(array[i]).Append(",");
            }
        }
        sb.Remove(sb.Length-1,1);
        Console.WriteLine(sb);
    }

하지만 시각화 출력을 위해서 WriteArray() 코드가 많이 지저분해졌기 때문에... 

 

4. 서로 다른 배열이 최소 4개 이상 시각적으로 표시해야 합니다.

5. 주석에 문제가 없어야 하고 깨끗하게 코딩되어 있어야 합니다.

6. 구문 오류나 논리적 오류는 없어야 합니다.

 

5번은 지켜지지 않은 것 같습니다. 그럼 콘솔로 선택 정렬 시각화를 마치겠습니다.