C#/C# 교과서

[C# 교과서] 31~32. 알고리즘과 절차 지향 프로그래밍, 개체 만들기

서니션 2023. 1. 9. 14:48
728x90
반응형

알고리즘

  • 문제를 해결하는 일련의 절차나 방법을 공식으로 표현한 풀이법
  • 프로그래밍을 할 때 생긴 문제의 해결 방법을 체계적으로 정리한 것
  • ‘문제 해결 능력’
  • 입력(input) → 처리(process) → 출력(output) 중 처리 단계가 알고리즘 단계
    • 입력 : 자료구조에서 담당하는 영역. 간단히 변수 및 배열의 데이터를 사용하고 나아가서는 컬렉션, 파일, 데이터베이스의 데이터를 사용하는 영역
    • 처리 : 알고리즘 처리 영역
    • 출력 : 화면에 보이는 UI를 담당하는 영역

근삿값 알고리즘

using System;
using System.Linq;
using static System.Console;

class Program2
{
    static void Main()
    {
        // 절댓값 구하기 로컬 함수 : Math.Abs() 함수와 동일한 기능을 구현
        int Abs(int num) => (num < 0) ? -num : num;

        // 1. 초기화
        int min = int.MaxValue; // 차이 값의 절댓값 중 최솟값이 담길 그릇

        // 2. 입력 : 이진수와 16진수로 표현
        int[] num = {0b1010,0x14,0b11110,0x1B,0b10001}; // {10,20,30,27,17}
        int target = 25; // target과 가까운 값
        int near = default; // 가까운 값 : 27

        // 3. 처리 : NEAR
        for (int i=0; i<num.Length; i++)
        {
            int abs = Abs(num[i] - target); // 차이 값의 절댓값
            if (abs < min)
            {
                min = abs; // MIN : 최솟값 알고리즘
                near = num[i]; // NEAR : 차이 값의 절댓값 중 최솟값일 때 값
            }
        }

        // 4. 출력 
        var minimum = num.Min(m=>Math.Abs(m-target));
        var closest = num.First(c=>Math.Abs(target-c)==minimum);
        WriteLine($"{target}와/과 가장 가까운 값(식):{closest}(차이:{minimum})");
        WriteLine($"{target}와/과 가장 가까운 값(문):{near}(차이:{min})");
    }
}

가까운 값 모두 구하기

using System;
using System.Collections.Generic;
using static System.Console;

class Program2
{
    static void Main()
    {
        int[] data = {10,20,23,27,17};
        int target = 25; 
        List<int> nears = new List<int>(); // 가까운 값들
        int min = Int32.MaxValue;

        // 1. MIN 알고리즘 : 차이의 최솟값 구하기
        for (int i=0; i<data.Length; i++)
        {
            if (Math.Abs(data[i] - target) < min)
            {
                min = Math.Abs(data[i]-target);
            }                
        }
        WriteLine($"차이의 최솟값 : {min}");

        // 2. NEAR 알고리즘 : 차이의 최솟값이 min인 값들을 다시 한 번 비교
        for (int i = 0; i < data.Length; i++)
        {
            if (Math.Abs(data[i]-target) == min)
            {
                nears.Add(data[i]); // 가까운 값을 모두 저장
            }
        }

        // 가까운 값 출력
        foreach (var n in nears)
        {
            WriteLine(n);
        }
    }
}

25와 가까운 데이터인 23과 27을 모두 구해서 리스트에 넣은 후 출력하는 예제


선택 정렬 알고리즘

  • 데이터 하나를 기준으로 나머지 데이터와 비교하여 가장 작거나 큰 데이터와 자리를 바꾸는 식으로 반복해서 비교하는 정렬 방법
  • 선택 정렬은 데이터 개수가 n개이면 전체 회전수는 n-1회
using System;
using static System.Console;

class Program2
{
    static void Main()
    {
        int[] data = {3,2,1,5,4};
        int N = data.Length;

        for (int i = 0; i < N-1; i++)
        {
            for (int j = i+1; j < N; j++)
            {
                if (data[i] > data[j]) // > 오름차순, < 내림차순
                {
                    int temp = data[i];
                    data[i] = data[j];
                    data[j] = temp;
                }
            }
        }
        for (int i = 0; i < N; i++)
        {
            Write($"{data[i]}\\t");
        }
        WriteLine();
    }
}

이진 검색 알고리즘

  • 주어진 데이터가 오름차순으로 정렬되어 있다고 가정
  • 의미 그대로 데이터를 절반으로 나누어서 검색하여 순차 검색보다 효율이 좋음
using System;
using static System.Console;

class Program2
{
    static void Main()
    {
        // 1. 입력
        int[] data = {1,3,5,7,9}; // 오름차순으로 정렬되었다고 가정
        int N = data.Length;
        int search = 3; // 검색할 데이터
        bool flag = false; // 플래그 변수
        int index = -1; // 인덱스 변수 : 찾은 위치

        // 2. 처리
        int low =0; // min : 낮은 인덱스
        int high = N-1; // max : 높은 인덱스
        while (low <= high)
        {
            int mid = (low + high) / 2; // 중간 인덱스 구하기
            if (data[mid]==search)
            {
                flag = true;
                index = mid;
                break; // 찾으면 플래그, 인덱스 저장 후 종료
            }
            if (data[mid]>search)
            {
                high = mid - 1; // 찾을 데이터가 작으면 왼쪽 영역으로 이동
            }
            else
            {
                low = mid + 1; // 찾을 데이터가 크면 오른쪽 영역으로 이동
            }
        }
        // 3. 출력
        if(flag)
        {
            WriteLine($"{search}을(를) {index} 위치에서 찾았습니다.");
        }
        else
        {
            WriteLine("찾지 못했습니다.");
        }
    }
}

병합 알고리즘

  • 배열 2개를 합쳐 하나로 만듦
using System;
using static System.Console;

class Program2
{
    static void Main()
    {
        // 1. 입력
        int[] first = {1,3,5};
        int[] second = {2,4};
        int M = first.Length; int N = second.Length; // M:N 관행
        int[] merge = new int[M+N]; // 병합된 배열
        int i=0; int j=0; int k=0; // i,j,k 관행

        // 2. 처리 (merge)
        while (i<M && j<N) // 둘 중 하나라도 배열 끝에 도달할 때까지
        {
            if (first[i] <= second[j]) // 작은 값을 merge 배열에 저장
            {
                merge[k++] = first[i++];
            }
            else
            {
                merge[k++] = second[j++];
            }
        }
        while (i < M) // 첫 번째 배열이 끝에 도달할 때까지
        {
            merge[k++] = first[i++];
        }
        while (j < N) // 두 번째 배열이 끝에 도달할 때까지
        {
            merge[k++] = second[j++];
        }

        // 3. 출력
        foreach (var m in merge)
        {
            Write($"{m}\\t");
        }
        WriteLine();
    }
}

최빈값 구하기 : MODE 알고리즘

  • 최빈값은 데이터 중에서 가장 많이 나타내는 값
  • 다른 알고리즘과 또 다른 모양으로 데이터 자체를 배열의 인덱스로 보고, 인덱스 개수 알고리즘을 적용하는 형태

그룹 알고리즘

  • 반별 총점이나 평균, 제품별 판매금액의 합 같은 그룹별로 구분되는 데이터의 통계를 산출할 때 사용

클래스와 개체

  • class 키워드로 생성한 것을 클래스
  • 클래스를 new 키워드로 사용하여 새로운 이름으로 만든 것을 개체
  • 모든 개체는 GetHashCode() 메서드를 호출하여 고유의 키 값을 제공받을 수 있음
  • 이 클래스로 만든 개체들은 서로 다른 인스턴스

인스턴스 메서드

  • 클래스 내에 선언된 메서드 중에서 static 키워드가 붙지 않은 메서드를 인스턴스 메서드라고 함
  • 인스턴스 메서드를 호출하려면 클래스의 인스턴스를 생성하여 개체를 만들어야 함
  • new 키워드를 사용
  • 인스턴스 메서드를 호출하려면 개체.인스턴스메서드이름();

Car 클래스의 인스턴스 생성 → Car car = new Car();

Car 클래스의 Go() 인스턴스 메서드 호출 → car.Go();


익명 형식

  • 클래스를 선언하지 않고 개체를 만드는 익명 형식도 있음
  • 특정 클래스 없이 이름 하나로 여러 속성을 모아 관리할 때 유용

정적 멤버와 인스턴스 멤버

  • static 키워드가 붙은 멤버에 접근할 때는 클래스 이름.멤버이름; 형태로 접근
  • static 키워드가 붙지 않은 멤버에 접근할 때는 클래스의 인스턴스를 생성하고 생성된 개체이름.멤버이름; 형태로 접근
  • static 키워드가 붙은 변수를 클래스 변수, 공유 개념
  • static이 붙지 않은 변수를 인스턴스 변수라고 함

ToString() 메서드 오버라이드

개체에 대한 문자열을 재정의


클래스 배열

클래스도 데이터 형식의 하나이므로 배열처럼 사용 가능

using System;

public class CategoryClass
{
    public void Print(int i) => Console.WriteLine($"카테고리 {i}");
}
class ClassArray
{
    static void Main()
    {
        CategoryClass[] categories = new CategoryClass[3];

        categories[0] = new CategoryClass();
        categories[1] = new CategoryClass();
        categories[2] = new CategoryClass();

        for (int i = 0; i < categories.Length; i++)
        {
            categories[i].Print(i);
        }
    }
}

var 키워드를 사용하여 클래스의 인스턴스 생성

var 키워드를 사용하면 코드가 살짝 짧아짐

 

public class ExamClass{}

ExamClass exam1 = new ExamClass();

var exam2 = new ExamClass();

 

긴 클래스 이름을 사용 할때는 간단히 var로 줄여 표현하는 것도 나쁘지 않음

  • 정적 멤버 호출은 가내수공업으로 필요할 때 바로 호출해서 사용하는 개념
  • 인스턴스 멤버 호출은 대기업 기성품처럼 설계도를 바탕으로 개체를 대량으로 만들어 사용
  • 프로그램 내에서 한두 번 호출하는 경우에 정적 멤버 사용
  • 여러 번 반복해서 사용하는 경우에 인스턴스 멤버 사용
728x90
반응형