js十大排序算法(下)

快速排序

快速排序即找一基准,小于的放在左数组,大于的放在右数组,并连接,进行递归。

function quickSort(arr){
        if(arr.length<=1){//如果数组只有一个数,就直接返回;
            return arr;
        }
        var num=Math.floor(arr.length/2);//找到中间数的索引值,如果是浮点数,则向下取整
        var newValue=arr.splice(num,1);//找到中间数的值
        var left=[],right=[];
        for(var i=0;i<arr.length;i++){
            if(arr[i]<newValue){
                left.push(arr[i]);//基准点的左边的数传到左边数组
            }else{
                right.push(arr[i]);//基准点的右边的数传到右边数组
            }
        }
        return quickSort(left).concat(newValue,quickSort(right));//递归不断重复比较,concat即连接数组
    }
    console.log(quickSort([21,5,45,12,56,8]));

堆排序

堆排序类似完全二叉树。利用堆顶元素最大的性质(但同行之间顺序未排),将堆顶元素取出放入新数组(循环时len–,视为新数组)中,将堆底元素放置堆顶,并重构,循环。

var len;      
function buildMaxHeap(arr) {   //建堆  
    len = arr.length;  
    // [n/2-1]表示的是最后一个有子节点 (本来是n/2(堆从1数起),但是这里arr索引是从0开始,所以-1)  
    for (var i = Math.floor(len/2)-1; i>=0; i--) {  
        maxHeapify(arr, i);  
    }  
    //对每一个节点(非叶节点),做堆调整  
}  
function maxHeapify(arr, i) {     //堆调整  
    var left = 2*i+1,    
        right = 2*i+2,   
        largest = i;   //i为该子树的根节点  

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

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

    if (largest != i) {  //即上面的if中有一个生效了  
        swap(arr, i, largest);  //交换最大的为父节点  
        maxHeapify(arr, largest);  //交换后,原值arr[i](往下降了)(索引保存为largest),  
        //作为根时,子节点可能比它大,因此要继续调整  
    }    
}   
function swap(arr, i, j) {  
    var temp = arr[i];    
    arr[i] = arr[j];  
    arr[j] = temp;  
}   
function heapSort(arr) {  
    buildMaxHeap(arr);  
    for (var i = arr.length-1; i > 0; i--) {  
        swap(arr, 0, i);  
        len--;  
        maxHeapify(arr, 0);  
    }  
    return arr;  
}  

var arr = [46,12,33,72,68,19,80,33];
heapSort(arr)
console.log(' after: ' + arr);

计数排序

计数排序要求数据集必须是已确定范围的整数。
统计数组中每个值为i的元素出现的次数,存入数组C的第i项,填充数组。

function countingSort(arr, maxValue) {
    var bucket =new Array(maxValue + 1),
        sortedIndex = 0;
        arrLen = arr.length,
        bucketLen = maxValue + 1;
 
    for (var i = 0; i < arrLen; i++) {
        if (!bucket[arr[i]]) {
            bucket[arr[i]] = 0;
        }
        bucket[arr[i]]++;
    }
 
    for (var j = 0; j < bucketLen; j++) {
        while(bucket[j] > 0) {
            arr[sortedIndex++] = j;
            bucket[j]--;
        }
    }
 
    return arr;
}

桶排序

桶排序利用了空间换时间的思想。即假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序,依次取出桶中数据。

/**
 * 桶排序
 * @param {Array} arr
 * @param {Number} bucketSize
 */
function bucketSort(arr, bucketSize = 5) {
  if (arr.length < 2) return arr;

  const buckets = createBucket(arr, bucketSize);
  return sortBuckets(buckets);
}

/**
 * @description:
 * @param {Array} arr=待排序数据
 * @param {Number} bucketSize=桶大小
 * @return:
 */
function createBucket(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.ceil((maxValue - minValue) / bucketSize);

  // 创建桶,用二维数组来存储
  const buckets = [];
  for (let i = 0; i <= bucketCount; i++) {
    buckets[i] = [];
  }

  // 计算把数据放到哪个桶
  for (let i = 0; i < arr.length; i++) {
    let bucketIndex = Math.floor((arr[i] - minValue) / bucketSize);
    buckets[bucketIndex].push(arr[i]);
  }
  return buckets;
}

/**
 * @description: 排序桶
 * @param {Array}  buckets
 * @return:
 */
function sortBuckets(buckets) {
  const sortArray = [];
  for (let i = 0; i < buckets.length; i++) {
    if (buckets[i] != null) {
      const sortBucket = insertionSort(buckets[i]);
      sortArray.push(sortBucket);
    }
  }
  return sortArray;
}

/**
 * @description: 插入排序
 * @param {Array} arr
 * @return: 排好序的arr
 */
function insertionSort(arr) {
  if (arr.length < 2) return arr;
  for (let i = 1; i < arr.length; i++) {
    let key = arr[i]; // 第一个元素已排好序,从第二个开始比较插入
    let j = i - 1;
    for (; j >= 0; j--) {
      if (arr[j] > key) {
        arr[j + 1] = arr[j]; // 比较,较大者,往后移
      } else {
        break;
      }
    }
    arr[j + 1] = key; // 插入对应的位置
  }
  return arr;
}

// 随机生成1000000个[1,100]区间内的整数
let arr1 = Array.from(
  { length: 1000000 },
  item => (item = Math.floor(Math.random() * Math.floor(100) + 1))
);

console.time("timer");
// console.log(`排序前的数据:${arr1}, 排序后的数据:${bucketSort(arr1, 5)}`);
bucketSort(arr1, 1); // 桶越小,排序越快,即桶个数越多,排序越快
console.timeEnd("timer");

基数排序

基数排序即按照键值的每位数字分配桶。
先按照个位分配10个桶中,后按顺序分到另一桶,再按照十位分配到10个桶中,进行循环。

var counter = [];
function radixSort(arr, maxDigit) {
    var mod = 10;
    var dev = 1;
    for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
        for(var j = 0; j < arr.length; j++) {
            var bucket = parseInt((arr[j] % mod) / dev);
            if(counter[bucket]==null) {
                counter[bucket] = [];
            }
            counter[bucket].push(arr[j]);
        }
        var pos = 0;
        for(var j = 0; j < counter.length; j++) {
            var value = null;
            if(counter[j]!=null) {
                while ((value = counter[j].shift()) != null) {
                      arr[pos++] = value;
                }
          }
        }
    }
    return arr;
}
1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。2.网上数据结构和算法的课程不少,但存在两个问题:1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级 3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。教程内容:本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。学习目标:通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页