Bootstrap

排序算法汇总(带图理解)

所有排序从小到大,本文排序算法全部都是以javascript为基础实现的

时间复杂的度

在这里插入图片描述

冒泡排序

在这里插入图片描述

/**
 * 冒泡排序:比较所有相邻的两个项,如果第一个比第二个大,则交换它们 (一般不用)
 *
 */
const bubbleSort = ( arr ) => {
  const { length } = arr;

  for(let i = 0; i < length; i++){
    for (let j = 0; j < length - 1 - i; j++) {
      if( arr[j] > arr[j+1] ) [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
    }
  }

  return arr;
}

选择排序

在这里插入图片描述

/**
 * 选择排序:找到数据结构中的最小值并将其放置在第一位,接着找到第二小的值并将其放在第二位,以此类推 (一般不用)
 *
 */
const selectionSort = ( arr ) => {
  const { length } = arr;
  let indexMin;

  for(let i = 0; i < length; i++){
    indexMin = i;

    for (let j = 0; j < length - 1 - i; j++){
      arr[indexMin] > arr[j] && (indexMin = j);
    }

    i !== indexMin && ([arr[i], arr[indexMin]] = [arr[indexMin], arr[i]]);
  }

  return arr;
}

插入排序

在这里插入图片描述

/**
 * 插入排序:从第二数据开始往前比较,找到合适的位置插入(也就是往前比较,小的在前面),完成以后来第二轮从第三数据开始,以此类推 (一般不用)
 *
 */
const insertionSort = ( arr ) => {
  const { length } = arr;
  let  temp;

  for(let i = 1; i < length; i++){
    let j = i;
    temp = arr[i];

    while(j > 0 && arr[j - 1] > temp){
      arr[j] = arr[j - 1];
      j--;
    }

    arr[j] = temp;
  }

  return arr;
}

归并排序

在这里插入图片描述

/**
 * 归并排序:把整体划分非为多个小块排序,最后汇总 (二分思想 + 递归 + 拆分)(常用)
 *
 */
const mergeSort = ( arr ) => {
  if(arr.length > 1){
    const { length } = arr;
    const middle = Math.floor(length / 2);
    const left = mergeSort(arr.slice(0, middle));
    const right = mergeSort(arr.slice(middle, length));
    arr = merge(left, right);
  }
  
  return arr;
}
const merge = ( left, right ) => {
  let i = 0, j = 0;
  const result = [];

  while(i < left.length && j < right.length){
    result.push(left[i] < right[j]? left[i++]: right[j++]);
  }

  return [...result, ...(i < left.length? left.slice(i): right.slice(j))];
}

快速排序

在这里插入图片描述

/**
 * 快速排序:和归并一样,不一样的地方是归并采用的是拆分,快速采用的两个指针(二分思想 + 递归 + 指针)(常用)
 *
 */
const quickSort = ( arr ) =>  {
  quick(arr, 0, arr.length - 1);
  return arr;
};
const quick = ( arr, left, right ) => {
  let index;
  if(arr.length > 1){
    index =  partition(arr, left, right);
    if(left < index - 1){
      quick(arr, left, index - 1);
    }
    if(right > index){
      quick(arr, index, right);
    }
  }
}
const partition = ( arr, left, right ) => {
  const pivot = arr[Math.floor((right + left) / 2)];
  let i = left, j = right;
  
  while(i <= j){
    while(arr[i] < pivot) i++;
    while(arr[j] > pivot) j--;

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

  return i;
}

计数排序

在这里插入图片描述

/**
 * :非常优秀的整数排序算法,找到数组中的最大值,创建临时数组(0到最大值),数组值对应临时数组下标重复+1,最后打印出来
 * 计数排序
 */
const countingSort = ( arr ) => {
  if (arr.length < 2) {
    return arr; 
  }

  const maxValue = findMaxValue(arr);

  const counts = new Array(maxValue + 1);
  arr.forEach(element => { 
    if (!counts[element]) {
      counts[element] = 0; 
    } 
    counts[element]++;
  });

  let sortedIndex = 0; 
  counts.forEach((count, i) => { 
    while (count > 0) {
      arr[sortedIndex++] = i;
      count--;
    } 
  });

  return arr;
}
const findMaxValue = ( arr ) => {
  let max = arr[0]; 
  for (let i = 1; i < arr.length; i++) { 
    if (arr[i] > max) { 
      max = arr[i]; 
    } 
  } 
 return max;
}
const findMinValue = ( arr ) => {
  let min = arr[0]; 
  for (let i = 1; i < arr.length; i++) { 
    if (arr[i] < min) { 
      min = arr[i]; 
    } 
  } 
 return min;
}

桶排序

在这里插入图片描述

/**
 * 桶排序:和计数一样,只是把计数过程换成了放在桶里
 *
 */
const bucketSort = ( arr, bucketSize = 5 ) => {
  if (arr.length < 2) { 
    return arr; 
  }
  const buckets = createBuckets(arr, bucketSize);
  return sortBuckets(buckets);
}
const createBuckets = ( arr, bucketSize ) => {
  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 bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
  const buckets = []; 
  for (let i = 0; i < bucketCount; i++) {
    buckets[i] = []; 
  }
  for (let i = 0; i < arr.length; i++) {
    const bucketIndex = Math.floor((arr[i] - minValue) / bucketSize);
    buckets[bucketIndex].push(arr[i]); 
  } 
  return buckets;
}
const sortBuckets = ( buckets ) => {
  const sortedArray = [];
  for (let i = 0; i < buckets.length; i++) {
    if (buckets[i] != null) {
      insertionSort(buckets[i]);
      sortedArray.push(...buckets[i]);
    }
  }
  return sortedArray;
}

基数排序

在这里插入图片描述
在这里插入图片描述

/**
 * 基数排序:比如10进制,先按照各位排序,在按照十位排序,以此类推
 *
 */
const radixSort = ( arr, radixBase = 10 ) => {
  if (arr.length < 2) {
    return arr; 
  }

  const minValue = findMinValue(arr); 
  const maxValue = findMaxValue(arr);

  let significantDigit = 1;
  while ((maxValue - minValue) / significantDigit >= 1) {
    arr = countingSortForRadix(arr, radixBase, significantDigit, minValue);
    significantDigit *= radixBase;
  } 
  return arr;
}
const countingSortForRadix = ( arr, radixBase, significantDigit, minValue) => {
  let bucketsIndex; 
  const buckets = []; 
  const aux = []; 
  for (let i = 0; i < radixBase; i++) {
    buckets[i] = 0; 
  } 
  for (let i = 0; i < arr.length; i++) {
    bucketsIndex = Math.floor(((arr[i] - minValue) / significantDigit) % radixBase);
    buckets[bucketsIndex]++;
  } 
  for (let i = 1; i < radixBase; i++) {
    buckets[i] += buckets[i - 1]; 
  } 
  for (let i = arr.length - 1; i >= 0; i--) {
    bucketsIndex = Math.floor(((arr[i] - minValue) / significantDigit) % radixBase);
    aux[--buckets[bucketsIndex]] = arr[i];
  } 
  for (let i = 0; i < arr.length; i++) {
    arr[i] = aux[i]; 
  } 
  return arr;
}
;