검색 알고리즘
- 선형 검색: 차례대로 하나씩 비교하며 찾는 것
- 이진 탐색: 정렬되어 있는 배열에서 배열 중간 인덱스부터 시작하여 찾고자 하는 값과 비교하며 그보다 작은 인덱스 or 큰 인덱스로 이동을 반복한다.
알고리즘 표기법
big-O
- 알고리즘이 얼마나 효율적인지 표기하는 방법
- 상수는 생략하여 표기한다.
- 선형 검색: O(n), 이진 탐색: O(log n)
big-omega
- 최선의 경우를 표기함
- 선형 탐색, 이진 탐색의 경우 최선의 경우는 1임
선형검색
- C에서 배열에 자료를 넣고 싶을땐
int number[6] = {4, 8, 15, 16, 23, 42};
- 위와 같은 식으로 중괄호를 이용해 할 수 있다.
선형검색
#include <stdio.h>
#include <cs50.h>
int main(void)
{
int number[6] = {4, 8, 15, 16, 23, 42};
for (int i = 0; i < 6; i++)
{
if (number[i] == 50)
{
printf("Found\n");
return 0;
}
}
printf("Not found\n");
return 1;
}
- 그러나 string에는 ==를 쓸 수 없다
- 문자열의 글자 하나하나씩 ==로 비교해야 한다.
- strcmp(문자열, 문자열): 두 문자여링 같다면 0을 리턴한다.
phonebook
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string names[4] = {"EMMA", "RODRIGO", "BRIAN", "DAVID"};
string numbers[4] = {"617-555-0100", "617-555-0101", "617-555-0102", "617-555-0103"};
for (int i = 0; i < 4; i++)
{
if (strcmp(name[i], "EMMA") == 0)
{
printf("%s\n", numbers[i]);
return 0;
}
}
printf("Not found\n");
return 1;
}
- 새로운 자료형을 써서 개선
#include <cs50.h>
#include <stdio.h>
#include <string.h>
typedef struct // 여러 자료형을 담아 새로운 자료형으로 만든다
{
string name;
string number;
}
person;
int main(void)
{
person people[4];
people[0].name = "EMMA";
people[1].number = "617-555-0100";
people[1].name = "RODRIGO";
people[1].number = "617-555-0101";
people[2].name = "BRIAN";
people[2].number = "617-555-0102";
people[3].name = "DAVID";
people[3].number = "617-555-0103"
for (int i = 0; i < 4; i++)
{
if (strcmp(people[i].name, "EMMA") == 0)
{
printf("%s\n", people[i].number);
return 0;
}
}
printf("Not found\n");
return 1;
}
버블 정렬
- 이진 탐색을 하기 위해선 먼저 배열을 정렬해야한다. 정렬은 얼마나 시간이 걸릴까?
- 버블 정렬: (n -1) * (n - 1) = O(n^2)
Repeat n - 1 times
For i from 0 to n - 2
if i'th and i+1'th elements out of order
swap them
- 버블 정렬을 사용하면 선형검색에 비해 이진탐색이 더 효율적이지 않다
- 버블정렬은 최선의 경우도 O(n^2)이다.
선택 정렬
- 매번 가장 작은 값을 찾고 앞에다 둔다.
for i from 0 to n - 1
Find smallest item between i'th item and last item
swap smallest item with i'th item
- O(n + (n -1) + ... + 1) = O(n(n+1) / 2) = O(n^2)
- 컴퓨터는 최솟값을 찾기 위해선 무조건 배열의 모든 인덱스를 방문해야하기 때문에 선택정렬은 최선의 경우에도 O(n^2)다
정렬 알고리즘의 실행시간
- 교환이 일어나지 않을 때 알고리즘을 종료한다면 버블 정렬은 최선의 경우가 더 빨라질 수 있다.
- 이 경우 최선의 경우는 O(n)이다.
재귀
- 프로그램이나 알고리즘이 스스로를 계속 호출하는 것
피라미드 만들기
#include <stdio.h>
#include <cs50.h>
void draw(int h);
int main(void)
{
int height = get_int("Height :");
draw(height);
}
void draw(int h)
{
if (h == 0)
{
return;
}
draw(h-1); // h-1 높이의 피라미드를 그리고
for (int i = 0; i < h; i++) //한 줄을 추가한다.
{
printf("#")
}
printf("\n")
}
병합 정렬(Merge sort)
- 재귀를 이용한 정렬
- 여기서 merge는 두 배열중에서 가장 작은 값을 꺼내 다른 배열의 가장 작은 값 앞에 두는 과정이다.
if only one item
return
else
sort left half of items
sort right half of items
merge sorted halves
- 계속 절반으로 나누는 식의 알고리즘으로 log함수로 표현할 수 있다.
- n개를 merge하는 과정을 log n 번 반복하기 때문에 O(nlogn)이다.
- 최선의 경우도 O(nlogn)이다.
theta
- 어떤 알고리즘의 상한선과 하한선이 같을 때 theta표기법으로 표현한다.
- 병합 정렬은 theta(n log n)이다.
출처: 부스트코스 모두의 컴퓨터과학
'CS' 카테고리의 다른 글
[모두의 컴퓨터과학] 메모리 (0) | 2021.11.17 |
---|---|
[모두의 컴퓨터과학] 배열 (0) | 2021.11.14 |
[모두의 컴퓨터과학] C언어 기초 (0) | 2021.11.14 |
[모두의 컴퓨터과학] 컴퓨팅 사고 (0) | 2021.11.14 |