Merge Sort View

class Arr {
    constructor() {
        this._list = [6, 10, 1, 9, 4, 8, 2, 7, 3];
        //this._list = new Array(10000).fill(0).map(v => Math.floor(Math.random() * 100) + 1);
    }
 
    mergeSort() {
        let timer     = this.timer(),
            listLen = this.list.length,
            loopLen = listLen / 2;
 
 
        //step 은 배열을 자르는 기준이 되기 때문에 이 로직의 핵심이에요.
        //step은 1부터 시작합니다. 
        //첫번째 포문은 배열의 길이만큼 도는데, step이 배열보다 커지지 않을때까지만 돌게 되요. 스텝은 현재 스텝길이의 * 2씩 증가. 
        //예를 들어 1 -> 2 -> 4 -> 8... 순으로 증가하는거죠.
        for(let step = 1; step < listLen; step *= 2)  
            //머지 함수에는 left와 right배열을 전달하는걸 주 목적으로 합니다. 
            //두번째 루프에는 0부터 len / 2 까지 순회하게 되는데 i += step이므로 step이 1일경우 
            //배열의 길이가 9라면, 배열을 매번 2개씩 절삭하므로 총 5번의 루프가 필요하게 되요.
            //즉 i < 4.5 가 되기때문에 총 5번 순회하는거지요 :) 
            //
            //start 값은 배열의 시작 위치부터 몇개씩 절삭시킬것인가에 대한 값이에요. 해당 값은 
            //step == 1
            //0 -> 2 -> 4 -> 6 -> 8... 
            //0 -> 0 + 1 * 2 -> 2 + 1 * 2 -> 4 + 1 * 2 ->...
            //
            //step == 2
            //0 -> 4 -> 8...
            //0 -> 0 + 2 * 2 -> 4 + 2 * 2 ->...
            //step == 4
            //0 -> 8 -> 16...
            //0 -> 0 + 4 * 2 -> 8 + 4 * 2 ->...
            for(let i = 0, start = 0, end = step; i < loopLen; i += step, start += step * 2, end = start + step) 
                this.merge(
                    this.getList(start, end), 
                    this.getList(end, start + step * 2), 
                    start
                );
            
        console.log(this.list,  timer() + ' : million Seccond');
    }
 
    getList(start, end) {
        return this.list.slice(start, end);
    }
 
    merge(left, right, start) {
 
        //홀수배열인 경우에 left[0]방은 무조건 있어요. 하지만 right[0]은 없을수도 있지요? 
        //그러니까 right[r] 을 확인하고 있으면 둘을 비교해서 작은 값을 result에 집어넣습니다.
        //없으면 그냥 왼쪽거만 남은거기땜에 그냥 왼쪽거에서 shift 하면 되요. :)
        //
        //결국엔 this.list에 몇번째부터 잘랐는지만 알면되는 start인자값을 통해서 n번부터 n번째에 값을 하나씩 최소값을 넣어주는거죠. 
        //start값은0 -> 1 -> 2.. 순으로 증가하게 될 테니까. 
        //
        //결국 지금 뽑아내는 값은 최소값만 뽑혀나오게 되는거니까요 ! 
        //배열의 몇번째방부터 몇번째방까지 순차적으로 최소값만 찔러넣어주게 되는거지요 :)
        for(let i = left.length + right.length; i--; start++) 
             this.list[start] = right[0] ? left[0] <= right[0] ? left.shift() : right.shift() : left.shift();
    }
    
    timer() {
        let start = new Date().getTime();
        return () =>  new Date().getTime() - start;
    }
 
    set list(list) {this._list = list;}
    get list() {return this._list;}
}
 
 
new Arr().mergeSort();