Skip to content

排序算法

冒泡排序

javascript
function bubbleSort(nums) {
  var n = nums.length;
  var temp, didSwap;

  for (var i = 0; i < n - 1; i++) {
    didSwap = false;
    for (var j = 0; j < n - i - 1; j++) {
      if (nums[j] > nums[j + 1]) {
        temp = nums[j];
        nums[j] = nums[j + 1];
        nums[j + 1] = temp;
        didSwap = true;
      }
    }

    // 正序情况下直接返回
    if (!didSwap) {
      return;
    }
  }
}

归并排序

javascript
class Merge {
  static temp;

  static sort(nums) {
    Merge.temp = [];
    Merge._sort(nums, 0, nums.length - 1);
  }

  static _sort(nums, lo, hi) {
    if (lo === hi) {
      return;
    }
    var mid = lo + Math.floor((hi - lo) / 2);
    Merge._sort(nums, lo, mid);
    Merge._sort(nums, mid + 1, hi);
    Merge.merge(nums, lo, mid, hi);
  }

  static merge(nums, lo, mid, hi) {
    for (var i = lo; i <= hi; i++) {
      Merge.temp[i] = nums[i];
    }
    // 合并两个升序数组 temp[lo,mid] temp[mid+1,hi]
    var i = lo,
      j = mid + 1;
    for (var p = lo; p <= hi; p++) {
      if (i === mid + 1) {
        // 左半边数组被全部合并
        nums[p] = Merge.temp[j++];
      } else if (j === hi + 1) {
        // 右半边数组被全部合并
        nums[p] = Merge.temp[i++];
      } else if (Merge.temp[i] > Merge.temp[j]) {
        nums[p] = Merge.temp[j++];
      } else {
        nums[p] = Merge.temp[i++];
      }
    }
  }
}

Merge.sort([5, 2, 3, 1]);

快速排序

js
function quickSort(nums) {
  // 洗牌降低退化成一个链表的概率
  shuffle(nums);
  sort(nums, 0, nums.length - 1);
  return nums;
}

function sort(nums, lo, hi) {
  if (lo >= hi) {
    return;
  }
  // 对 nums[lo..hi] 进行切分
  // 使得 nums[lo..p-1] <= nums[p] < nums[p+1..hi]
  var p = partition(nums, lo, hi);

  sort(nums, lo, p - 1);
  sort(nums, p + 1, hi);
}

function partition(nums, lo, hi) {
  // [lo, i) <= pivot && (j, hi] > pivot
  var pivot = nums[lo];
  var i = lo + 1,
    j = hi;

  while (i <= j) {
    while (i < hi && nums[i] <= pivot) i++;
    while (j > lo && nums[j] > pivot) j--;

    // 此时 [lo, i) <= pivot && (j, hi] > pivot
    if (i >= j) {
      break;
    }
    [nums[i], nums[j]] = [nums[j], nums[i]];
  }
  [nums[lo], nums[j]] = [nums[j], nums[lo]];
  return j;
}

// 洗牌算法,将输入的数组随机打乱
function shuffle(nums) {
  for (var i = nums.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));

    [nums[i], nums[j]] = [nums[j], nums[i]];
  }
}
js
function quickSort(nums) {
  const stack = [[0, nums.length - 1]];

  while (stack.length) {
    const [lo, hi] = stack.pop();

    if (lo >= hi) {
      continue;
    }

    let p = partition(nums, lo, hi);

    stack.push([lo, p - 1]);
    stack.push([p + 1, hi]);
  }

  return nums;
}

堆排序

javascript
function heapSort(nums) {
  buildMaxHeap(nums);
  for (var i = nums.length - 1; i >= 0; i--) {
    // 交换堆顶与最后一个元素
    [nums[i], nums[0]] = [nums[0], nums[i]];
    // 下沉堆顶元素到合适位置
    maxHeapify(nums, 0, i);
  }
}

function buildMaxHeap(nums) {
  var n = nums.length;
  // 从低向上构建大堆
  for (var i = Math.floor(n / 2) - 1; i >= 0; i--) {
    maxHeapify(nums, i, n);
  }
}

/**
 *
 * @param {*} nums
 * @param {*} i 父节点下标
 * @param {*} len 堆大小
 */
function maxHeapify(nums, i, len) {
  var largest = i;
  var left = i * 2 + 1;
  var right = i * 2 + 2;

  if (left < len && nums[left] > nums[largest]) {
    largest = left;
  }
  if (right < len && nums[right] > nums[largest]) {
    largest = right;
  }

  if (largest !== i) {
    // 上浮大元素
    [nums[i], nums[largest]] = [nums[largest], nums[i]];
    // 下沉小元素
    maxHeapify(nums, largest, len);
  }
}