1. 程式人生 > >資料結構與演算法--排序(冒泡、選擇、歸併、快速排序、堆排序)

資料結構與演算法--排序(冒泡、選擇、歸併、快速排序、堆排序)

/**
 * 氣泡排序
 * @param arr
 */
function bubbleSort(arr) {
  let len = arr.length;
  for (let i =0; i < arr.len; i++) {
    for (let j = 0; i < len - i - 1; j++) {
      if (arr[j] > arr[j+1]) {
        [arr[j], arr[j+1]] = [arr[j+1], arr[j]];
      }
    }
  }
}

/**
 * 選擇排序
 * @param arr
 */
function selectSort(arr) {
  let len = arr.length, minIndex;
  for (let i = 0; i < len; i++) {
    minIndex = i;
    for (let j = i + 1; j < len; j++) {
      if (arr[j] > arr[minIndex]) {
        minIndex = j;
      }
    }

    if (i != minIndex) {
      [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
    }
  }
}


/**
 *
 * @param arr
 */
function insertionSort(arr) {
  let len = arr.length, j , temp;
  for (let i = 1; i < len; i++) {
    temp = arr[i];
    j = i;
    while (j > 0 && arr[j-1] > temp) {
      arr[j-1] = arr[j];
      j--;
    }

    arr[j] = temp;
  }
}

/**
 * 歸併排序:先遞迴將陣列拆分成小的陣列,然後再將小陣列排序歸併
 * @param arr
 */
function mergeSort(arr) {
  let array = mergeSortRec(arr);


  function mergeSortRec(arr) {
    let len = arr.length;
    if (len === 1) {
      return arr;
    }

    let mid = Math.floor(len / 2),
      left = arr.slice(0, mid),
      right = arr.slice(mid, len);


    return merge(mergeSortRec(left), mergeSortRec(right));
  }

  function merge(left, right) {
    let result = [],
      il = 0,
      ir = 0;
    while (il < left.length && ir < right.length) {
      if (left[il] < right[ir]) {
        result.push(left[il++]);
      } else {
        result.push(right[ir++]);
      }
    }

    while (il < left.length) {
      result.push(left[il++])
    }

    while (ir < right.length) {
      result.push(right[ir++])
    }

    return result;
  }
}

// 快速排序
function quickSort(arr) {
  quick(arr, 0, arr.length);

  function quick(arr, left, right) {
    let index = partition(arr, left, right);

    if (left < index - 1) {
      quick(arr, left, index - 1);
    }

    if (index < right) {
      quick(arr, index, right);
    }
  }

  function partition(arr, left, right) {
    let piort = arr[Math.floor((left + right) / 2)],
      i = left,
      j = right;

    while (i < j) {
      while (arr[i] < piort) {
        i++;
      }

      while (arr[j] > piort) {
        j--;
      }

      if (i <= j) {
        [arr[i], arr[j]] = [arr[j], arr[i]];
        i++;
        j--;
      }
    }

    return i;
  }
}

function heapSort(arr) {

  function max_heapify(start, end) {
    // 建立父節點和子節點下標
    let dad = start;
    let son = dad * 2;
    // 若子節點下標超出範圍則直接跳出函式
    if (son >= end) {
      return;
    }

    // 比較父節點的兩個子節點,並選擇最大的
    if (son + 1 < end && arr[son] < arr[son + 1]) {
      son++;
    }

    // 如果父節點小於子節點,則交換對應的值,再繼續子節點和孫節點的比較
    if (arr[dad] < arr[son]) {
      // 交換
      [arr[dad], arr[son]] = [arr[son], arr[dad]];
      max_heapify(son, end);
    }
  }

  let len = arr.length;
  // 初始化,i 從最後一個父節點開始調整
  for (let i = Math.floor(len / 2) - 1; i >= 0; i--) {
    max_heapify(i,len);
  }

  // 現將第一個元素和已構建成的最大堆(陣列第一個元素)交換,再重新調整,直到排序完畢
  for(let i = len - 1; i > 0; i++) {
    [arr[0], arr[i]] = [arr[i], arr[0]];
    max_heapify(0, i);
  }
}