前端算法

JavaScript 排序集锦

2020-01-16  本文已影响0人  24KBING

JavaScript 之排序集锦

1⃣️ 快速排序

快速排序

单独开辟两个存储空间 leftright 来存储每次递归比 target 小和大的序列,每次递归直接返回 lefttargetright 拼接后的数组.
浪费大量存储空间,写法简单.

function quickSort(array) {
  if (array.length < 2) {
    return array;
  }
  const target = array[0];
  const left = [];
  const right = [];
  for (let i = 0; i < array.length; i++) {
    if (array[i] < target) {
      left.push(array[i]);
    } else {
      right.push(array[i]);
    }
  }
  return;
  quickSort(left).concat([target], quickSort(right));
}

2⃣️ 归并排序

利用归并的思想实现的排序方法。

该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。(分治法将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

归并排序 归并排序

分割数组时直接将数组分割为两个数组,合并时直接合并数组

function merge(front, end) {
  const temp = [];
  while (front.length && end.length) {
    if (front[0] < end[0]) {
      temp.push(front.shift());
    } else {
      temp.push(end.shift());
    }
  }
  while (front.length) {
    temp.push(front.shift());
  }
  while (end.length) {
    temp.push(end.shift());
  }
  return temp;
}

function mergeSort(array) {
  if (array.length < 2) {
    return array;
  }
  const mid = Math.floor(array.length / 2);
  const front = array.slice(0, mid);
  const end = array.slice(mid);
  return merge(mergeSort(front), mergeSort(end));
}

3⃣️ 选择排序

选择排序

每次循环选取一个最小的数字放到前面的有序序列中.

function selectionSort(array) {
  for (let i = 0; i < array.length - 1; i++) {
    let minIndex = i;
    for (let j = i + 1; j < array.length; j++) {
      if (array[j] < array[minIndex]) {
        minIndex = j;
      }
    }
    [array[minIndex], array[i]] = [array[i], array[minIndex]];
  }
  return array;
}

4⃣️ 插入排序

将左侧序列看成一个有序序列,每次将一个数字插入该有序序列。
插入时,从有序序列最右侧开始比较,若比较的数较大,后移一位。

插入排序
function insertSort(array) {
  for (let i = 1; i < array.length; i++) {
    let target = i;
    for (let j = i - 1; j >= 0; j--) {
      if (array[target] < array[j]) {
        [array[target], array[j]] = [array[j], array[target]];
        target = j;
      } else {
        break;
      }
    }
  }
  return array;
}

5⃣️ 冒泡排序

冒泡排序
function bubbleSort(array) {
  for (let j = 0; j < array.length; j++) {
    let complete = true;
    for (let i = 0; i < array.length - j - 1; i++) {
      // 比较相邻数
      if (array[i] > array[i + 1]) {
        [array[i], array[i + 1]] = [array[i + 1], array[i]];
        complete = false;
      }
    }
    // 没有冒泡结束循环
    if (complete) {
      break;
    }
  }
  return array;
}

6⃣️ 堆排序

堆排序 堆排序
// 构建大顶堆, 从第一个非叶子节点开始, 进行下沉操作.
function createHeap(array) {
  const len = array.length;
  const start = parseInt(len / 2) - 1;
  for (let i = start; i >= 0; i--) {
    adjust(array, i, len);
  }
}
// 将第target个元素进行下沉, 孩子节点有比他大的就下沉
function adjust(array, target, len) {
  for (let i = 2 * target + 1; i < len; i = 2 * i + 1) {
    // 找到孩子节点中最大的
    if (i + 1 < len && array[i + 1] > array[i]) {
      i = i + 1;
    }
    // 下沉
    if (array[i] > array[target]) {
      [array[i], array[target]] = [array[target], array[i]];
      target = i;
    } else {
      break;
    }
  }
}
function heapSort(array) {
  createHeap(array);
  // 交换第一个和最后一个元素, 然后重新调整大顶堆
  for (let i = array.length - 1; i > 0; i--) {
    [array[i], array[0]] = [array[0], array[i]];
    adjust(array, 0, i);
  }
  return array;
}

7⃣️ 希尔排序

希尔排序的核心在于间隔序列的设定.既可以提前设定好间隔序列,也可以动态的定义间隔序列.动态定义间隔序列的算法是《算法(第4版)》 的合著者 Robret Sedgewick 提出的.

希尔排序 希尔排序
function shellSort(array) {
  let len = array.length;
  let gap = parseInt(len / 2);
  let i, j, temp, result;
  // 复制数组
  result = array.slice(0);
  while (gap > 0) {
    for (i = gap; i < len; i++) {
      temp = result[i];
      j = i - gap;
      while (j >= 0 && temp < result[j]) {
        result[j + gap] = result[j];
        j = j - gap;
      }
      result[j + gap] = temp;
    }
    gap = parseInt(gap / 2);
  }
  return result;
}

8⃣️ 计数排序

计数排序 计数排序
function countingSort(array, maxValue) {
  let bucket = new Array(maxValue + 1);
  let sortIndex = 0;
  let bucketLen = maxValue + 1;
  for (let i = 0; i < array.length; i++) {
    if (!bucket[array[i]]) {
      bucket[array[i]] = 0;
    }
    bucket[array[i]]++;
  }
  for (let j = 0; j < bucketLen; j++) {
    while (bucket[j] > 0) {
      array[sortIndex++] = j;
      bucket[j]--;
    }
  }
  return array;
}

9⃣️ 桶排序

桶排序 桶排序
function bucketSort(arr, bucketSize) {
  if (arr.length === 0) {
    return arr;
  }
  let minValue = arr[0];

  let maxValue = arr[0];

  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < minValue) {
      minValue = arr[i]; //输入数据的最小值
    } else if (arr[i] > maxValue) {
      maxValue = arr[i]; //输入数据的最大值
    }
  } //桶的初始化
  const DEFAULT_BUCKET_SIZE = 5; //设置桶的默认数量为5
  bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;

  let bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
  let buckets = new Array(bucketCount);

  for (let i = 0; i < buckets.length; i++) {
    buckets[i] = [];
  } //利用映射函数将数据分配到各个桶中
  for (let i = 0; i < arr.length; i++) {
    buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);
  }

  arr.length = 0;

  for (let i = 0; i < buckets.length; i++) {
    insertionSort(buckets[i]); //对每个桶进行排序,这里使用了插入排序
    for (let j = 0; j < buckets[i].length; j++) {
      arr.push(buckets[i][j]);
    }
  }

  return arr;
}

🔟 基数排序

基数排序 基数排序
function radixSort(arr, n, radix) {
  if (!radix) {
    //默认为十进制
    radix = 10;
  }
  if (!n) {
    //如果未指定关键词位数将自动使用首个元素的位数作为n
    n = arr[0].toString().length;
  }
  var i,
    j,
    tmp,
    num,
    queues = [],
    q = arr.slice();
  for (i = 0; i < radix; i++) {
    queues.push([]); //生成Q[0]~Q[radix-1]
  }
  for (i = 0; i < n; i++) {
    //LSD低位起始
    while (q.length > 0) {
      tmp = q.shift();
      num = Math.floor((tmp / Math.pow(radix, i)) % radix); //获取某位数值
      //这里这个转换只能搞得动十进制= =其他就会有问题 因为不能直接用其他进制来进行运算 所以考虑使用字符串处理
      queues[num].push(tmp);
    }
    for (j = 0; j < radix; j++) {
      //重构q
      while (queues[j].length > 0) {
        q.push(queues[j].shift());
      }
    }
  }
  return q;
}
上一篇 下一篇

猜你喜欢

热点阅读