js实现十大经典排序算法

  1. 冒泡排序
// 从第一个开始一个一个向后比对、交换
// 改进了的冒泡排序
function sort (arr) {
  let len = arr.length
    ,mark;
  for (let i = 0; i < len - 1; i++) {
    mark = 0;
    for (let j = 0; j < len - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        mark = 1;
        [arr[j], arr[j+1]] = [arr[j+1], arr[j]];
      }
    }
    if (!mark) {
      break
    }
  }
  return arr
}
  1. 选择排序
// 从i(令他最小),开始寻找包含i的最小的数,i++(循环前面步骤)
function sort (arr) {
    let len = arr.length
        ,minIndex; //选择的最小值得index
    for (let i = 0; i < len - 1; i++) {
        minIndex = i;
        for (let j = i + 1; j < len; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j
            }
        }
        [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
    }

    return arr;
}
  1. 希尔排序
// 先分为若干子序(通过间隔, 间隔逐渐缩小为1),再分别进行插入排序
function sort (arr) {
  let grap = 1
    ,len = arr.length
    ,cur
    ,j;
  
  while(grap<len / 3) {
    grap = grap*3 +1
  }
  for (grap; grap > 0; grap = Math.floor(grap / 3)) {
    for (let i = grap; i < len; i++) {
      cur = arr[i];
      for (j = i - grap; j >= 0 && arr[j] > cur; j -= grap) {
        arr[j + grap] = arr[j];
      }
      arr[j + grap] = cur;
      console.log(arr)
    }
  }
  return arr
}
  1. 插入排序
// 从i=1 开始,默认i=0是有序,和前面序列比较找到合适位置插入
function sort (arr) {
    let len = arr.length
      ,preindex
      ,cur;
    for (let i = 1; i < len; i++) {
        preindex = i - 1;
        cur = arr[i];
        while(arr[preindex]>cur && preindex>=0) {
            arr[preindex + 1]  = arr[preindex];
            preindex--;
        }
        arr[preindex+1] = cur
        console.log(arr)
    }
    return arr
}
  1. 归并排序
// 建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。先将其划分为若干最小块,将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序  小 =》 大
function mergeSort (arr) {
  let len = arr.length;
  if (len < 2) {
    return arr
  }
  let midle = Math.ceil(len / 2)
    ,left = arr.slice(0, midle)
    ,right = arr.slice(midle);
  return merge(mergeSort(left), mergeSort(right))
}

function merge (left, right) {
  let _arr = [];
  while(left.length>0 && right.length>0) {
    if (left[0] <= right[0]) {
      _arr.push(left.shift());
    } else {
      _arr.push(right.shift());
    }
  }

  if (left.length > 0) {
    _arr = _arr.concat(left)
  }

  if (right.length > 0) {
    _arr = _arr.concat(right);
  }
  console.log(_arr)
  return _arr;
}
  1. 快速排序
// 建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。先将其划分为若干最小块,将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序  小 =》 大
function mergeSort (arr) {
  let len = arr.length;
  if (len < 2) {
    return arr
  }
  let midle = Math.ceil(len / 2)
    ,left = arr.slice(0, midle)
    ,right = arr.slice(midle);
  return merge(mergeSort(left), mergeSort(right))
}

function merge (left, right) {
  let _arr = [];
  while(left.length>0 && right.length>0) {
    if (left[0] <= right[0]) {
      _arr.push(left.shift());
    } else {
      _arr.push(right.shift());
    }
  }

  if (left.length > 0) {
    _arr = _arr.concat(left)
  }

  if (right.length > 0) {
    _arr = _arr.concat(right);
  }
  console.log(_arr)
  return _arr;
}
  1. 堆排序
function heapSort (arr) {
  let len = arr.length;

  // 根据传入的i节点的位置调整一 i 为根节点的子树
  function heapify (arr, i) {
    let lChildIdx = 2 * i + 1 // 左孩子
      ,rChildIdx = 2 * i + 2  // 右孩子
      ,maxIdx = i;          // 此时设父节点为最大

    if (lChildIdx<len && arr[lChildIdx]>arr[maxIdx]) {
      maxIdx = lChildIdx;
    }
    if (rChildIdx<len && arr[rChildIdx]>arr[maxIdx]) {
      maxIdx = rChildIdx;
    }
    if (maxIdx !== i) {
      // 即 当前,某个子节点的值大于父节点,此时标记这个节点是父节点,更换现在父节点的值与实际父节点的值,
      [arr[maxIdx], arr[i]] = [arr[i], arr[maxIdx]];
      heapify(arr, maxIdx);
    }
  }

  // 构建大顶堆(升序), 二叉树非叶节点比叶节点少一个 Math.floor(len/2-1)
  // 从第一个叶节点开始,保证后面的顺序。
  for(let i = Math.floor(len / 2); i >= 0; i--){
    heapify(arr,i);
  }
  // 调整大顶堆,并排序
  for (let i = len-1; i >= 0; i--) {
    [arr[0], arr[i]] = [arr[i], arr[0]];
    len --; // 其中调整的是
    heapify(arr, 0);
  }

  return arr
}
  1. 计数排序
function countingSort(arr) {
  let len = arr.length
    ,max = arr[0]
    ,countArr = [];

  // 寻找最大和最小 的index
  for (let i = 1; i < len; i++) {
    if (arr[i] > max) {
      max = arr[i];
    }
  }
  // 得到相应的大小
  countArr.length = max + 1;
  countArr.fill(0);
  // 技术开始
  for (let i = 0; i < len; i++) {
    countArr[arr[i]]++;
  }
  // 还原
  for (let i = 0, j = 0, len = countArr.length; i < len; i++) {
    for (let k = 0; k < countArr[i]; k++) {
      arr[j] = i;
      j++;
    }
  }
  return arr
}
  1. 桶排序
// 插入排序
function insertSort (arr) {
  let len = arr.length
    ,preindex
    ,cur;
  for (let i = 1; i < len; i++) {
    preindex = i - 1;
    cur = arr[i];
    while(arr[preindex]>cur && preindex>=0) {
      arr[preindex + 1]  = arr[preindex];
      preindex--;
    }
    arr[preindex+1] = cur
  }
  console.log(arr)
  return arr
}

// 桶排序,一个桶相当于这个数组中的数的一个区间,不同范围的数在不同的桶,然后不同的桶内再排序,再对桶排序
function bucketSort (arr, len = arr.length) {
  const DEFAULT_BUCKET_SIZE = 5; // 桶大小,决定了这个桶最大数和最小数的最大的可能的差为 多少
  let min = arr[0]
    ,max = arr[0]
    ,bucketSize = DEFAULT_BUCKET_SIZE //
    ,bucketCount
    ,bucketArr = [];

  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < min) {
      min = arr[i];                // 输入数据的最小值
    } else if (arr[i] > max) {
      max = arr[i];                // 输入数据的最大值
    }
  }
  // 桶和桶的数组初始化
  bucketCount = Math.floor((max - min) / bucketSize) + 1
  for (let i = 0; i < bucketCount; i++) {
    bucketArr[i]=[];
  }

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

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

  return arr;
}
  1. 基数排序
function radixSort(arr, maxDigit) {
  let mod = 10
    ,dev = 1
    ,counter = []
    ,index; // 用于更新arr

  for (let i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
    counter = [];
    for(let j = 0; j < arr.length; j++) {
      let bucket = Math.floor((arr[j] % mod) / dev);
      if(!counter[bucket]) {
        counter[bucket] = [];
      }
      counter[bucket].push(arr[j]);
    }

    index = 0;
    for(let j = 0; j < counter.length; j++) {
      // 遍历这一列统一基数的数
      if(counter[j]) {
        for (let i = 0, len = counter[j].length; i < len; i++) {
          arr[index++] = counter[j][i]
        }
      }
    }
  }
  return arr;
}

参考地址1
参考地址2

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值