~51일차~
코딩테스트 스터디에서 강의를 듣고 정리해보았다.
//선택 정렬 함수
function selectionSort(arr) {
  for (let i= 0; i <arr.length; i++) {
    let minIndex = i;   // 가장 작은 원소의 인덱스
    for (let j = i +1; j < arr.length; j++) {
      if (arr[minIndex] > arr[j] {
        minIndex = j;
      }
  }
  //스와프(swap)
  let temp = arr[i];
  arr[i] = arr[minIndex];
  arr[min Index] = temp;
  }
}
//버블 정렬 함수
function bubbleSort(arr) {
  for (let i = arr.length - 1; i > 0; i--) {
    for (let j = 0; j < i; j++) {
      if (arr[j] < arr[j + i]) {
        let temp = arr[j];
        arr[j] = arr[j + i];
        arr[j + 1] = temp;
      }
    }
  }
}
각 단계에서 현재 원소가 삽입될 위치를 찾는다
적절한 위치에 도달할 때까지 반복적으로 왼쪽으로 이동
동작과정이 매우 직관적이나, O(N2)의 시간 복잡도를 가져 비효율적
처음에 첫번째 원소는 정렬이 되어 있다고 고려
선택적보다는 효율적일 수 있음
//삽입 정렬 함수
function insertionSort(arr) {
  for (let i =1; i < arr.length; i++) {
    for (let j = i; j > 0; j--) {
      // 인덱스 j부터 1까지 1씩 감소하며 반복
      if (arr[j] < arr[j-i]) {
        // 한 칸씩 왼쪽으로 이동
        //스와프(swap)
        let temp = arr[j];
        arr[j] = arr[j - 1];
        arr[j - 1] = temp;
      } else {
        // 작은 데이터를 만나면 그 위치에서 멈춤
        break;
      }
    }
  }
}
-각 원소를 적절한 위치에 삽입하는 정렬 기법
-일반적으로 재귀 함수를 이용하여 구현
-> 큰 문제를 작은 문제로  "분할하는 방식이 동일한" 경우가 많기 때문
-더 이상 쪼갤 수 없는 크기가 될 때까지 계속하여 분할
시간 복잡도 O(NlogN)을 보장하는 빠른 정렬 알고리즘 중 하나
분할 정복을 이용하는 가장 기본적인 정렬알고리즘
1. 분할(divide) : 정렬할배열(큰 문제)을 같은 크기의 부분 배열(작은 문제) 2개로 분할
2. 정복(conquer): 부분 배열 정렬
3. 조합(combine): 정렬된 부분 배열을 하나의 배열로 다시 병합
직관적으로 생각
-> 높이가 O(logN), 너비 O(N)인 정사각형과 유사
//(정복 이후) 병합(merge) !!수행!! 함수
function merge(arr, left, mid, right) {
  let i = left; //왼쪽 배열에서 첫번째 원소를 가르킴
  let j = mid + 1; // 오른쪽 배열에서 첫번째 원소를 가르킴
  let k = left; // 결과 배열의 인덱스
  
   // 각각 한칸씩 오른쪽으로 움직이며 비교
  while (i <= mid && j <= right) {
    // 왼쪽을 가리키는 값 <= 오른쪽을 가리키는 값
    if (arr[i] <= arr[j]) sorted[k++] = arr [i++]; // 더 작은 값이 결과 배열에 들어감(오름차순 형태)
    else sorted[k++] = arr[j++];
  }
  // 왼쪽 배열에 대한 처리가 다 끝난 경우
  if (i > mid) {
    for (; j <= right; j++) sorted[k++] = arr[j];
  }
  //오른쪽 배열에 대한 처리가 다 끝난 경우
  else {
    for (; <= mid; i++) sorted[k++] = arr[i];
  }
  // 정렬된 배열 결과를 원본 배열에 반영하기
  for (let x = left; x <= right; x++) {
    arr[x] = sorted[x];
  }
}
//실질적 병합 정렬(merge sort) 함수
//left:첫번째 원소의 인덱스, right:마지막 원소의 인덱스
function mergeSort(arr, left, right) {
  //원소가 1개인 경우 해당 배열은 정렬이 된 상태로 이해 가능
  if (left < right) {
    //원소가 2개 이상이라면
    let mid = parseInt((left + right) / 2); //2개 부분 배열로 분할 (divide)
    mergeSort(arr, left, mid); // 왼쪽 부분 배열 정렬 수행(conquer)
    mergeSort(arr, mid + 1,, right); // 오른쪽 부분 배열 정렬 수행(conquer)
    merge(arr, left, mid, right); // 정렬된 2개의 배열을 하나로 병합(combine)
  }
}