woohot 2023. 4. 10. 17:45

처음 알고리즘을 배울때 배웠던 내용이 정렬이었다.

정렬 종류도 많고 헛갈리 때가 있어 정리 하려한다.

 


 

 

1. 삽입 정렬 , 시간 : O(n^2) , 공간 : O(n)

 

삽입 정렬이란?

자료 배열의 모든 요소를 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여, 자신의 위치를 찾아 삽입함으로써 정렬을 완성하는 알고리즘이다.

function insertSort(list){   
    let key,j ;   
    for(const i in list){       
        key = list[i];       
        j = i-1;       
        while( j >= 0 && key < list[j] ){           
            swap(list,j,j+1); 
            j--; 
       }
       list[j+1] = key;
    }
    return list;
}

function swap(list,a,b){
    let temp = list[a];
    list[a] = list[b];
    list[b] = temp;
}

https://ko.wikipedia.org/wiki/%EC%82%BD%EC%9E%85_%EC%A0%95%EB%A0%AC

 

삽입 정렬 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 삽입 정렬(揷入整列, insertion sort)은 자료 배열의 모든 요소를 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여, 자신의 위치를 찾아 삽입함으로써 정렬

ko.wikipedia.org

 

 

2. 선택 정렬 , 시간 : O(n^2) , 공간 : O(n)

 

선택 정렬이란? 

 제자리 정렬 알고리즘의 하나로, 다음과 같은 순서로 이루어진다.

  1. 주어진 리스트 중에 최소값을 찾는다.
  2. 그 값을 맨 앞에 위치한 값과 교체한다(패스(pass)).
  3. 맨 처음 위치를 뺀 나머지 리스트를 같은 방법으로 교체한다.
let list = [4,2,7,9,12,3];

function swap(list,a,b){
    let temp = list[a];
    list[a] = list[b];
    list[b] = temp;
}

const minSelectionSort = (list) => { // 최소 선택 정렬 , 오름차순
    console.log('minSelectionSort start');
    for(let i =0 ; i< list.length; i++){
        let tmp = i;
        for(let j=i+1; j<list.length ; j++){
            console.log(list[i],list[j])
            if(list[tmp] >= list[j]) {
                tmp=j
            }
        }
        swap(list, i,tmp) 
  }
    return list;
}

const maxSelectionSort = (list) => { //최대 선택 정렬 , 내림차순
    console.log('minSelectionSort start')
    for(let i =list.length -1 ; i>=0 ; i--){
        let tmp = i;
        for(let j=i-1; j>=0 ; j--){
            console.log(list[i],list[j])
            if(list[tmp] < list[j]) {
                tmp=j 
            }
        }
        swap(list, i,tmp)
    }
    return list;
}

console.log('min : ',minSelectionSort(list));
console.log('max : ',maxSelectionSort(list));

https://ko.wikipedia.org/wiki/%EC%84%A0%ED%83%9D_%EC%A0%95%EB%A0%AC

 

선택 정렬 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 선택 정렬(選擇整列, selection sort)은 제자리 정렬 알고리즘의 하나로, 다음과 같은 순서로 이루어진다. 주어진 리스트 중에 최소값을 찾는다. 그 값을 맨 앞에 위

ko.wikipedia.org

 

 

3. 버블 정렬 , 시간 : O(n^2) , 공간 : O(n)

 

버블 정렬이란?

정렬 알고리즘 중 하나이다. 시간 복잡도 O(n^2)

로 상당히 느리지만, 코드가 단순하기 때문에 자주 사용된다. 

function swap(list,a,b){
    let temp = list[a];
    list[a] = list[b];
    list[b] = temp;
}

const bubbleSort = (list) => {
    for(let i = 0; i < list.length ; i++){
        for(let j=1; j<list.length ; j++){
            if(list[j-1] > list[j]){
                swap(list, j,j-1)
            }
        }
    }
    return list;
}

console.log('bubble' , bubbleSort(list));

https://ko.wikipedia.org/wiki/%EB%B2%84%EB%B8%94_%EC%A0%95%EB%A0%AC

 

버블 정렬 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 버블 정렬 또는 거품 정렬(-整列, 영어: bubble sort 버블 소트[*], sinking sort 싱킹 소트[*])은 정렬 알고리즘 중 하나이다. 시간 복잡도가 O ( n 2 ) {\displaystyle O(n^{2})}

ko.wikipedia.org

 

 

4. 합병 정렬 , 시간 : O(nlog n) , 공간 : O(2n)

병합 정렬(영어: merge sort 머지 소트[*])은 O(n log n) 비교 기반 정렬 알고리즘이다. 일반적인 방법으로 구현했을 때 이 정렬은 안정 정렬에 속하며, 분할 정복 알고리즘의 하나이다.

 

구현 방법에는

톱 다운 구현, 바텀 업 구현 ,외부 병합 정렬  있다.


const merge = (left, right) => {
    const sortedArr = [];
    while (left.length && right.length) {      //left[0]이 더작을 경우 같을때는 누가 먼저 들어가도 상관X
      if (left[0] <= right[0]) {
        sortedArr.push(left.shift());
      } else {
        sortedArr.push(right.shift());
      }
    }   
    //left,right 둘 중 하나는 요소가 남아있기 때문에 sortedArr 뒤에 붙여서 출력   
    //비어있으면 spread Syntax에도 아무것도 없기 때문에 그냥 다 붙여준다.
    return [...sortedArr, ...left, ...right]; 
}   

const mergeSort = (arr) => {
    if (arr.length === 1) return arr;
    const boundary = Math.ceil(arr.length / 2);    //slice로 해주기 때문에 원본 arr은 손상 없다.
    const left = arr.slice(0, boundary);
    const right = arr.slice(boundary);   
    //요소가 1개 일 때까지 재귀를 실행해 요소가 1개일 때 두 left,right부터   
    //차근차근 merge(정렬해서 합치기)해주면 된다.
    return merge(mergeSort(left), mergeSort(right));
}

const arr = [7, 4, 3, 2, 1, 6, 5];
const sortedArray = mergeSort(arr);
console.log(arr); //[7, 4, 3, 2, 1, 6, 5]
console.log(sortedArray); //[1, 2, 3, 4,5, 6, 7]

https://ko.wikipedia.org/wiki/%ED%95%A9%EB%B3%91_%EC%A0%95%EB%A0%AC

 

합병 정렬 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 합병 정렬 또는 병합 정렬(영어: merge sort 머지 소트[*])은 O(n log n) 비교 기반 정렬 알고리즘이다. 일반적인 방법으로 구현했을 때 이 정렬은 안정 정렬에 속하며,

ko.wikipedia.org

 

 

5. 퀵 정렬 , 시간 :  O(nlog n)  최악의경우 , O(n^2) , 공간 :

다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속한다.

퀵 정렬은 n개의 데이터를 정렬할 때, 최악의 경우에는 O(n2)번의 비교를 수행하고, 평균적으로 O(n log n)번의 비교를 수행한다. 분할 정복 전략을 사용한다

 

 

구현 방법에는 in place , !(not) in place 방법이 있는데 , in place 방법이 메모리 사용량이 적다.

 

중복되는 데이터는 순차적으로 pivot에 넣어 , 정렬 전 중복 데이터의 순서가 바뀌지 않는 stable한 정렬을 구현

Not In Place

const quickSort = (array) => {
    if(array.length < 2){
        return array;
    }
    const pivot = [array[0]];
    const left = [];
    const right = [];    // console.log('pivot : ' ,pivot );
    for(let i = 1; i< array.length ; i++){
        if( array[i] < pivot ){
            left.push(array[i]);
        }else if(array[i] > pivot){
            right.push(array[i]);
        }else{
            pivot.push(array[i]);
        }
    }
    console.log(`left : ${left} , pivot : ${pivot} , right : ${right}`);
    return quickSort(left).concat(pivot, quickSort(right));
}


 

메모리 공간이 절약된다  .왼쪽과 오른쪽 값을 교환하는 과정에서 중복값의 위치가 바뀔 수 있으므로 unstable한 정렬 방법

const inPlaceQuick = (array, left=0, right=array.length -1 ) => {
        if(left >= right){
            return ;
        }
    const divide = (array , left, right, pivot) => {
        console.log(`array: ${array}, left: ${array[left]}, pivot: ${pivot}, right: ${array[right]}`);
        while(left <= right){
            while(array[left] < pivot){
                left++;
            }
            while(array[right] > pivot){
                right--;
            }
            if(left <= right){
                let swap = array[left];
                array[left] = array[right];
                array[right] = swap;
                left++;
                right--;
            }
        }
        return left;
    }
    const mid = Math.floor((left+right)/2);
    const pivot = array[mid];
    const partition = divide(array, left, right, pivot);
    inPlaceQuick(array , left , partition -1 );
    inPlaceQuick(array , partition , right );
        return array;
}

const sorted = inPlaceQuick([5,3,7,1,9]);
console.log(sorted);

https://ko.wikipedia.org/wiki/%ED%80%B5_%EC%A0%95%EB%A0%AC

 

퀵 정렬 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 퀵 정렬(Quicksort)은 찰스 앤터니 리처드 호어가 개발한 정렬 알고리즘이다. 다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속한다. 퀵 정렬은 n개의 데

ko.wikipedia.org

 

 

 

힙 정렬 시간 :  O(n^2)  최악의경우 , O(n^2) , 공간 : O(1)

최대  트리나 최소 힙 트리를 구성해 정렬을 하는 방법으로서, 내림차순 정렬을 위해서는 최소 힙을 구성하고 오름차순 정렬을 위해서는 최대 힙을 구성하면 된다.

 

const heapSort = (arr) => { 
    let tmp;
    for(let i = arr.length-1 ; i>= 0 ; i--){
        arr = heapMaker(arr,i);
        if(arr[0] > arr[i]){
            tmp = arr[i];
            arr[i] = arr[0];
            arr[0] = tmp;
        }
    }
    return arr;
}

const heapMaker = (arr, lastidx) => {
    let idx = parseInt(lastidx/2)-1;
    while(idx >= 0 ){
        const left = arr[idx*2+1];
        const right = arr[idx*2+2];
        if( left >= right && arr[idx] < left){
            tmp = arr[idx];
            arr[idx*2 + 1] = tmp;
            arr[idx] = left;
        }else if( right > left && arr[idx] < right ){
            tmp = arr[idx];
            arr[idx*2 +2] = tmp;
            arr[idx] = right;
        }
        idx--;
    }
    return arr;
}

 

https://ko.wikipedia.org/wiki/%ED%9E%99_%EC%A0%95%EB%A0%AC

 

힙 정렬 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 힙 정렬(Heap sort)이란 최대 힙 트리나 최소 힙 트리를 구성해 정렬을 하는 방법으로서, 내림차순 정렬을 위해서는 최소 힙을 구성하고 오름차순 정렬을 위해서

ko.wikipedia.org

 

 

이 외에도 아래 정렬이 있지만 위에 부분이 잘 나오기때문에 먼저 정리했다.

 

피존홀 정렬

기수 정렬

계수 정렬

 

#참고

공간 복잡도

https://velog.io/@aonee/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B3%B5%EA%B0%84-%EB%B3%B5%EC%9E%A1%EB%8F%84

 

정렬관련 포스팅

https://hsp1116.tistory.com/33

https://evan-moon.github.io/2018/10/13/sort-algorithm/

 

여러 정렬알고리즘

https://nohack.tistory.com/79

 

퀵소트 

https://im-developer.tistory.com/135