카테고리

asm (27) bootloader_x86_grub (1) C (92) compile (11) config (76) CPP (13) CSS (1) debugging (7) gimp (1) Go (1) html (1) Java (1) JavaScript (1) kernel (19) LibreOffice (3) Linux system progamming (21) MFC (1) opencv (4) OpenGL (1) PHP (1) Python (4) qemu (29) shell (3) socket (7) troubleshooting (2) ubuntu18.04 (2) windows (1)

2019/01/03

자료구죠 키워드 정리.

나열 방법 -> 탐색 및 검색을 잘 하게 하는 알고리즘 구조

선형: 연결 리스트, stack, queue, dequeu
비선형: Tree

stack
push: pop == 입력 방향, 출력방향이 하나임. 입출구가 하나인 박스공간.

Queue: 줄서기
Push:Pop == 단방향

Dequeu: 상호작용
Push:Pop == 양방향
a) 선택 정렬
->선택 정렬은 비교는 많지만, 교환은 적은 알고리즘이다.
 장점: 정렬된 상태를 역순으로 정렬시 효율적이다.
 단점: 정렬된 데이터에 소수의 데이터 추가시 이를 다시 정렬하기 위해서는 최악이다.

$ cat ages.txt
Bob 12
Jane 48
Mark 3
Tashi 54

$ sort -k2 -n ages.txt
Mark 3
Bob 12
Jane 48
Tashi 54

sort -n -k 7 /path/to/input
find . -type f -iname "pattern*" -ls |sort -n -k 7
find . -type f -iname "pattern*" -ls |sort -r -n -k 7

-r -정렬 결과를 반대.
-n -숫자 정렬
-k 7 -POS1에서 키 시작 즉, 7 번에서 정렬 키 시작
-s 정렬 안정화

b) 버블 정렬
시간복잡도: O(N^2)

->데이터를 하나씩 비교할 수 있어서 정밀하게 비교 가능하나 비교횟수가 많아지므로
성능면에서 좋은 방법이 아니다. 첫번째 원소부터 마지막 원소까지 비교가 끝나면 가장 큰 원소를 마지막 자리로 정렬한다.

# Bash 배열 정렬
# Bubble 정렬 사용
 
# 정적 배열 입력
arr = (10 8 20 100 12)
 
echo "Array in original order"
echo ${arr[*]}
 
# 버블 정렬 수행 
for ((i = 0; i<5; i++))
do
     
    for((j = i; j<5-i-1; j++))
    do
     
        if ((${arr[j]} > ${arr[$((j+1))]}))
        then
            # swap
            temp = ${arr[$j]}
            arr[$j] = ${arr[$((j+1))]} 
            arr[$((j+1))] = $temp
        fi
    done
done
 
echo "Array in sorted order :"
echo ${arr[*]}

출력 :
Array in sorted order :
8 10 12 20 100

c) 퀵정렬 >
시간복잡도
최악- O(N^2)
평균- O(NlogN)

->캐시라는 지역적 특성에 의해 실제적으로 NlogN보다 좋은 성능을 보여 가장 많이 사용하는 정렬이다. 단점으로는 안정성이없다. 안정성이 없다는 것은 정렬되기 이전의 데이터 동일한 데이터끼리의 순서를 정렬 후에도 유지하고 있는가이다.

d) 삽입정렬 >
시간복잡도 : O(N^2)

버블정렬이 조금 비효율적인 면이 있기에 비교횟수를 효율적으로 줄이기 위해 고안된 삽입정렬이다. 버블정렬은 비교대상의 메모리 값이 정렬되어 있음에도 불구하고 비교연산을 하는 부분이 있는데 삽입정렬은 비교적 비교횟수를 줄이고 , 정렬된 값은 한번도 교환이 일어나지 않고 N-1의 비교만 일어난다.


e) 쉘 정렬 >
시간복잡도: O(N^1.25)

삽입정렬의 개념을 확대하여 일반화한 정렬방법이다. 알고리즘이 간단하여 간단히 구현할 수 있다. 수행능력도 삽입정렬보다 우수하다. 멀리있는 레코드들 끼리 비교 및 교환 될 수 있으므로, 어떤 데이터가 제 위치에서 멀리 떨어져 있다면 여러 번의 교환이 발생하는 버블정렬의 단점을 해결 할 수 있다.

f) 병합 정렬>
시간복잡도: O(NlogN)

작은 단위부터 정렬해서 정렬된 단위들을  계속 병합해가면서 정렬하는 방식이다. 알고리즘 중에 가장 간단하고 쉽게 떠올릴 수 있는 방법이다. 안정성이 있으며 상당히 좋은 성능을 나타낸다. 큰 결점은 데이터 크기만한 메모리가 더 필요하다는 것이다.

g) 버킷정렬>
버킷정렬은 정렬대상의 키들을 일정한 범위로 구분해 버킷(통)에 넣고 그 버킷을 각각 정렬하는 방법이다.

특징: 키가 어떤 범위내에서 키값이 확률적으로 균등하게 분포되어 있을 때 적용하면 효과가 좋다.
  실행시간: 버켓에 넣는 시간 O(n)+정렬시간

사용하기 좋은 예: "Person 객체를 담은 아주 큰 배열이 있다고 하자. 이 배열에 담긴 객체들을 나이순으로 정렬하라"
  여기서 두 힌트를 얻을 수 있다.
1. 큰 배열이므로 효율성이 중요하다.
2. 나이에 따라 정렬하는 것이므로, 그 값의 범위가 좁게 제한되어 있음을 이용할 수 있다.

정렬 알고리즘들을 살펴보면, 아마 버킷정렬 또는 기수 정렬이 가장 적합하리라는 것을 눈치 챌 수 있을 것이다. 버킷을 작게 만들 수 있고(각 버킷에 1년)O(n)으 실행시간을 달성할 수 있다. 그렇다면 값의 범위가 작을 때 사용하기 좋은 정렬?

댓글 없음:

댓글 쓰기