Selection Sort (선택 정렬)

[예시 코드]
#include <cstdio>
#include <cstdlib>
 
using namespace std;
 
void selection_sort(int *nums, int N) {
    int min, min_idx;
    
    for(int i=0; i<N-1; i++) {
        min_idx = i;
        min = nums[i];
        for(int j=i+1; j<N; j++) {
            if(min > nums[j]) {
                min = nums[j];
                min_idx = j;
            }
        }
        nums[min_idx] = nums[i];
        nums[i] = min;
    }
}
 
int main(void) {
    int N, *nums;
    scanf("%d"&N);
 
    nums = (int*)malloc(sizeof(int)*N);
 
    for(int i=0; i<N; i++)
        scanf("%d"&nums[i]);
 
    selection_sort(nums, N);
 
    for(int i=0; i<N; i++)
        printf("%d ", nums[i]);
 
    printf("\n");
 
    free(nums);
 
    return 0;
}
cs


[내용]

N개의 숫자를 정렬할 때, index를 0~N-2 에서부터 N-1 까지 보면서, 가장 작은 수를 선택해서 맨 앞과 바꿔주면서 정렬해 나가는 방식이다.

맨 처음부터 마지막 중 가장 작은 수를 찾아서 첫 번째와 바꿔주고,

두 번째부터 마지막 중 가장 작은 수를 찾아서 두 번째와 바꿔주는 식으로 진행한다.


[특징]

- 비교 연산이 많이 사용된다.

- 값을 실제로 교환하는 횟수는 상대적으로 적다.



Bubble Sort (버블 정렬)

[예시 코드]

#include <cstdio>
#include <cstdlib>
 
using namespace std;
 
void bubble_sort(int *nums, int N) {
    int temp;
 
    for(int i=0; i<N-1; i++) {
        for(int j=1; j<N-i; j++) {
            if(nums[j-1> nums[j]) {
                temp = nums[j-1];
                nums[j-1= nums[j];
                nums[j] = temp;
            }
        }
    }
}
 
int main(void) {
    int N, *nums;
    scanf("%d"&N);
 
    nums = (int*)malloc(sizeof(int)*N);
 
    for(int i=0; i<N; i++) {
        scanf("%d"&nums[i]);
    }
 
    bubble_sort(nums, N);
 
    for(int i=0; i<N; i++)
        printf("%d ", nums[i]);
 
    printf("\n");
 
    free(nums);
 
    return 0;
}
cs



[내용]

앞쪽부터 뒷쪽까지 2개의 숫자씩을 비교해가며, 오른쪽이 더 작은 경우 값을 교환해준다.

이를 N번 진행하면 전체 숫자의 정렬이 완료된다.


[특징]

- 비교와 값의 교환이 많이 발생한다.



Insertion Sort (삽입 정렬)

[예시 코드]
#include <cstdio>
#include <cstdlib>
 
using namespace std;
 
void insertion_sort(int *nums, int N) {
    int t, idx;
 
    for(int i=1; i<N; i++) {
        t = nums[i];
        idx = i;
        while(nums[idx-1> t && idx > 0) {
            nums[idx] = nums[idx-1];
            idx--;
        }
        nums[idx] = t;
    }
}
 
int main(void) {
    int N, *nums;
    scanf("%d"&N);
 
    nums = (int*)malloc(sizeof(int)*N);
 
    for(int i=0; i<N; i++) {
        scanf("%d"&nums[i]);
    }
 
    insertion_sort(nums, N);
 
    for(int i=0; i<N; i++)
        printf("%d ", nums[i]);
 
    printf("\n");
 
    free(nums);
 
    return 0;
}
cs


[내용]

idx를 1부터 N-1까지 실행하며, 해당 인덱스에 있는 숫자를 그 앞쪽에서 맞는 위치에 삽입해준다.


[특징]

- 다른 정렬 알고리즘들에 비해서빠른 편이다.

- 정렬해야 할 숫자의 개수가 적은 경우에 유용하다.



Indirection을 이용한 Insertion Sort (삽입 정렬)

[예시 코드]

#include <cstdio>
#include <cstdlib>
 
using namespace std;
 
void insertion_sort(int *nums, int *idx, int N) {
    int t, tIdx;
 
    for(int i=0; i<N; i++)
        idx[i] = i;
 
    for(int i=1; i<N; i++) {
        t = idx[i];
        tIdx = i;
        
        while(nums[idx[tIdx-1]] > nums[t] && tIdx > 0) {
            idx[tIdx] = idx[tIdx-1];
            tIdx--;
        }
 
        idx[tIdx] = t;
    }
}
 
int main(void) {
    int N, *nums, *idx;
    scanf("%d"&N);
 
    nums = (int*)malloc(sizeof(int)*N);
    idx = (int*)malloc(sizeof(int)*N);
 
    for(int i=0; i<N; i++) {
        scanf("%d"&nums[i]);
    }
 
    insertion_sort(nums, idx, N);
 
    for(int i=0; i<N; i++)
        printf("%d ", nums[idx[i]]);
 
    printf("\n");
 
    free(nums);
    free(idx);
 
    return 0;
}
cs


[내용]

- Insertion Sort에서 값을 하나씩 복사시키지 않고, 인덱스용 배열을 따로 생성하고 인덱스만 정렬한다.


[특징]

- 원래 값이 있는 배열은 자료가 변하지 않고 그대로 유지된다.

- sorting된 순서대로 접근하려면, 인덱스 배열을 순서대로 접근하며 이를 인덱스로 사용하여 숫자 배열을 사용하면 된다.



Shell Sort (쉘 정렬)

[예시 코드]

#include <cstdio>
#include <cstdlib>
 
using namespace std;
 
void shell_sort(int *nums, int N) {
    int v, k;
 
    for(int h = N/2; h>0; h/=2) {
        for(int i=0; i<h; i++) {
            for(int j=i+h; j<N; j+=h) {
                v = nums[j];
                k = j;
                while(k > h-1 && nums[k-h] > v) {
                    nums[k] = nums[k-h];
                    k -= h;
                }
                nums[k] = v;
            }
        }
    }
}
 
int main(void) {
    int N, *nums;
    scanf("%d"&N);
 
    nums = (int*)malloc(sizeof(int)*N);
 
    for(int i=0; i<N; i++)
        scanf("%d"&nums[i]);
 
    shell_sort(nums, N);
 
    for(int i=0; i<N; i++)
        printf("%d ", nums[i]);
 
    printf("\n");
 
    free(nums);
 
    return 0;
}
cs


[내용]

- 기본적인 접근법은 insertion sort와 동일하다.

- h는 스텝 사이즈이다.

- 처음부터 2개씩 비교를 하는 것이 아니라, 스텝 사이즈만큼 떨어트려서 있는 것들끼리만 비교하여 insertion sort 방식으로 정렬을 하고, 스텝 사이즈를 줄이며 이를 반복한다.




[특징]

- 정렬하려는 숫자의 개수와 관계 없이 속도가 빠른 편이다.

- 추가적인 메모리가 필요하지 않다.



Quick Sort (퀵 정렬)

[예시 코드]

#include <cstdio>
#include <cstdlib>
 
void quick_sort(int *nums, int N) {
    int i, j, v, temp;
 
    if(N > 1) {
        v = nums[N-1];    // Pivot
        i = -1;
        j = N-1;
 
        while(true) {
            while(nums[++i] < v);
            while(nums[--j] > v);
 
            if(i >= j)
                break;
 
            temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
 
        temp = nums[i];
        nums[i] = nums[N-1];
        nums[N-1= temp;
 
        quick_sort(nums, i);
        quick_sort(nums+i+1, N-i-1);
    }
}
 
int main(void) {
    int N, *nums;
    scanf("%d"&N);
 
    nums = (int*)malloc(sizeof(int)*N);
 
    for(int i=0; i<N; i++)
        scanf("%d"&nums[i]);
 
    quick_sort(nums, N);
 
    for(int i=0; i<N; i++)
        printf("%d ", nums[i]);
 
    printf("\n");
 
    free(nums);
 
    return 0;
}
cs


[내용]

- quick sort는 나눠서 정렬하는 것이다.

- 인덱스 i는 왼쪽에서 오른쪽으로, 인덱스 j는 오른쪽에서 왼쪽으로 이동한다.

- 우선, 현재 주어진 숫자 배열의 범위에서 가장 오른쪽에 있는 값을 pivot으로 설정한다.

- 인덱스 i를 오른쪽으로 이동하며 가장 먼저 나오는 pivot보다 큰 값의 인덱스까지 이동한다.

- 인덱스 j는 왼쪽으로 이동하며 가장 먼저 나오는 pivot보다 작은 값의 인덱스까지 이동한다.

- 만약에 i가 j의 오른쪽에 있다면 (i와 j가 이동하다가 서로 지나쳤다면) 그만하고, 그렇지 않으면 계속하여 i와 j를 구해서 서로 값을 바꿔준다.

- 이렇게 하면 현재 i가 있는 곳을 기준으로 왼쪽은 pivot보다 작은 값들이, 오른쪽은 pivot보다 큰 값들이 위치하게 된다.

- recursion으로 현재 i보다 왼쪽과 오른쪽을 각각 한번씩 호출해준다.

- 다 끝나고나면 정렬이 된다.

- cf. recursion termination 조건은 if(N > 1)이다. (N이 1이 되면 종료)


[특이 사항]

- 이미 정렬된 경우에는 별로 좋지 않기 때문에 pivot을 랜덤으로 지정해주는 방법도 있다.

- 간격이 클 때는 quick sort를 사용하고, 작으면 insertion sort를 사용하여 병행하는 방법도 있다.




'C & C++ > Reference' 카테고리의 다른 글

C/C++ - 파일 입출력  (0) 2018.04.05
C++ string 정리  (3) 2018.01.23

[파일 열기와 닫기]

FILE *fp = fopen("input.txt""r");    // 파일 포인터 선언과 열기
fclose(fp);                            // 파일 닫기
cs




[파일 열기 방식]

 플래그

역할 

파일이 존재하지 않는 경우 

파일이 존재하는 경우 

파일 쓰기 시도할 경우 

 r

 읽기 모드

NULL을 반환 

존재하는 파일을 엶 

안 됨 

 r+

 읽기/쓰기

NULL을 반환 

존재하는 파일을 엶 

내용과 관계없이 겹쳐서 처음부터 써짐 

 쓰기

새로운 파일 생성 

새로운 파일 생성 

잘 써짐 

 w+

쓰기/읽기 

새로운 파일 새성 

새로운 파일 생성 

잘 써짐 

 a

쓰기(추가작성) 

새로운 파일 생성 

존재하는 파일을 엶 

뒤쪽에 추가로 써짐 

a+ 

쓰기/읽기 

새로운 파일 생성 

존재하는 파일을 엶 

뒤쪽에 추가로 써짐 

rb 

2진 읽기 모드 

NULL을 반환

존재하는 파일을 엶 

안 됨 

r+b 

2진 읽기/쓰기 

 NULL을 반환

존재하는 파일을 엶 

내용과 관계없이 겹쳐서 처음부터 써짐 

 wb

2진 쓰기 

새로운 파일 생성 

새로운 파일 생성 

잘 써짐 

 w+b

2진 쓰기/읽기 

 새로운 파일 생성

새로운 파일 생성 

잘 써짐 

ab 

 2진 쓰기(추가)

 새로운 파일 생성

존재하는 파일을 엶 

뒤쪽에 추가로 써짐 

 a+b

 2진 쓰기/읽기

새로운 파일 생성 

존재하는 파일을 엶 

뒤쪽에 추가로 써짐 



[fscanf, fprintf]

int x;
 
fscanf(fp, "%d"&x);
 
fprintf(fp, "%d", x);
cs

scanf, printf와 같이 사용하면 되는데, file pointer를 앞부분에 파라미터로 전달해준다.




[fgets, fputs]

char buf[BUF_SIZE];
 
fgets(buf, 30, fp);
 
fputs("Hello World", fp);
cs

- string 단위로 입출력을 실행하는 기능이다.

- fgets(char 배열, 읽을 크기, 파일 포인터)

- fputs(문자열, 파일 포인터)




[fseek]

fseek(fp, offset, FLAG);

cs


- 파일 포인터의 위치를 변경할 수 있다.

- FLAG로 다음을 사용할 수 있다.

  (1) SEEK_SET : 파일 처음

  (2) SEEK_CUR : 현재 위치

  (3) SEEK_END : 파일의 끝



[fwrite, fread - 바이너리 파일로 열었을 경우 사용 가능]

size_t fwrite(const void *buffer, size_t size, size_t count, FILE *stream);
cs


- 반환 : 파일에 쓴 데이터 항목의 수(count)



size_t fread (void *buffer, size_t size, size_t count, FILE *stream);
cs


- 반환 : 파일에서 읽어온 데이터 항목의 수(count)



'C & C++ > Reference' 카테고리의 다른 글

정렬 알고리즘  (0) 2018.05.02
C++ string 정리  (3) 2018.01.23

https://dev-repository.tistory.com/57


예쁘게 다시 정리해서 새 블로그에 작성하였습니다.


'C & C++ > Reference' 카테고리의 다른 글

정렬 알고리즘  (0) 2018.05.02
C/C++ - 파일 입출력  (0) 2018.04.05

+ Recent posts