常用的排序算法总结

冒泡排序

冒泡排序算法的原理如下:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
js 复制代码
    function bubbleSort(arr) {
        let len = arr.length;
        for (let i = 0; i < len; i++) {
            for (let j = 0; j < len - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    let temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        return arr;
    }

选择排序

选择排序算法的原理如下:

  1. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
  2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
  3. 重复第二步,直到所有元素均排序完毕。
js 复制代码
   function selectionSort(arr) {
       let len = arr.length;
       let minIndex, temp;
       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;
               }
           }
           temp = arr[i];
           arr[i] = arr[minIndex];
           arr[minIndex] = temp;
       }
       return arr;
   }

插入排序

插入排序算法的原理如下:

  1. 从第一个元素开始,该元素可以认为已经被排序;
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  5. 将新元素插入到该位置后;
  6. 重复步骤2~5。
js 复制代码
   function insertionSort(arr) {
       let len = arr.length;
       let preIndex, current;
       for (let i = 1; i < len; i++) {
           preIndex = i - 1;
           current = arr[i];
           while (preIndex >= 0 && arr[preIndex] > current) {
               arr[preIndex + 1] = arr[preIndex];
               preIndex--;
           }
           arr[preIndex + 1] = current;
       }
       return arr;
   }

归并排序

归并排序是一种分治算法,它将数组分成两个子数组,分别对子数组进行排序,然后将排好序的子数组合并成一个大的有序数组。

js 复制代码
   function mergeSort(arr) {
       if (arr.length < 2) {
           return arr;
       }
       
       const middle = Math.floor(arr.length / 2);
       const left = arr.slice(0, middle);
       const right = arr.slice(middle);
       
       return merge(mergeSort(left), mergeSort(right));
   }

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

快速排序

快速排序算法的原理如下:

  1. 从数列中挑出一个元素,称为 "基准"(pivot);
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
js 复制代码
   function quickSort(arr) {
       if (arr.length <= 1) {
           return arr;
       }
       
       const pivot = arr[0];
       const left = [];
       const right = [];
       
       for (let i = 1; i < arr.length; i++) {
           arr[i] < pivot ? left.push(arr[i]) : right.push(arr[i]);
       }
       
       return quickSort(left).concat(pivot, quickSort(right));
   }

堆排序

堆排序利用了堆的数据结构,将待排序的序列构建成一个最大堆,然后将堆顶元素(最大值)与堆末尾元素交换,将最大值沉到数组末端,再重新调整堆结构,重复此过程直至整个序列有序。

js 复制代码
   function heapSort(arr) {
       let len = arr.length;
       
       for (let i = Math.floor(len / 2) - 1; i >= 0; i--) {
           heapify(arr, len, i);
       }
       
       for (let i = len - 1; i > 0; i--) {
           [arr[0], arr[i]] = [arr[i], arr[0]];
           heapify(arr, i, 0);
       }
       
       return arr;
   }

   function heapify(arr, len, i) {
       let largest = i;
       let left = 2 * i + 1;
       let right = 2 * i + 2;
       
       if (left < len && arr[left] > arr[largest]) {
           largest = left;
       }
       
       if (right < len && arr[right] > arr[largest]) {
           largest = right;
       }
       
       if (largest !== i) {
           [arr[i], arr[largest]] = [arr[largest], arr[i]];
           heapify(arr, len, largest);
       }
   }

计数排序

  1. 计数排序算法的原理如下:
  2. 找出待排序的数组中最大和最小的元素;
  3. 统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
  4. 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
  5. 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
js 复制代码
   function countingSort(arr) {
       let len = arr.length;
       let max = Math.max(...arr);
       let count = new Array(max + 1).fill(0);
       let result = [];
       
       for (let i = 0; i < len; i++) {
           count[arr[i]]++;
       }
       
       for (let i = 0; i <= max; i++) {
           while (count[i]-- > 0) {
               result.push(i);
           }
       }
       
       return result;
   }

桶排序

堆排序算法的原理如下:

  1. 将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
  2. 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
  3. 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
js 复制代码
   function bucketSort(arr, bucketSize = 5) {
       if (arr.length === 0) {
           return arr;
       }
       
       let min = Math.min(...arr);
       let max = Math.max(...arr);
       let bucketCount = Math.floor((max - min) / bucketSize) + 1;
       let buckets = new Array(bucketCount);
       
       for (let i = 0; i < bucketCount; i++) {
           buckets[i] = [];
       }
       
       for (let i = 0; i < arr.length; i++) {
           let bucketIndex = Math.floor((arr[i] - min) / bucketSize);
           buckets[bucketIndex].push(arr[i]);
       }
       
       let sortedArray = [];
       for (let i = 0; i < bucketCount; i++) {
           insertionSort(buckets[i]);
           sortedArray = sortedArray.concat(buckets[i]);
       }
       
       return sortedArray;
   }

基数排序

基数排序是一种非比较排序算法,它根据元素的位数进行排序。它将整数按照位数从低位到高位依次进行排序。

js 复制代码
   function radixSort(arr) {
       const max = Math.max(...arr);
       const maxLength = String(max).length;
       let buckets = Array.from({ length: 10 }, () => []);
       
       for (let i = 0; i < maxLength; i++) {
           for (let j = 0; j < arr.length; j++) {
               const digit = Math.floor(arr[j] / Math.pow(10, i)) % 10;
               buckets[digit].push(arr[j]);
           }
           arr = buckets.flat();
           buckets = Array.from({ length: 10 }, () => []);
       }
       
       return arr;
   }

希尔排序

希尔排序算法的原理如下:

  1. 选择一个增量序列 t1,t2,......,tk,其中 ti > tj, tk = 1;
  2. 按增量序列个数 k,对序列进行 k 趟排序;
  3. 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
js 复制代码
   function shellSort(arr) {
       let len = arr.length;
       for (let gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {
           for (let i = gap; i < len; i++) {
               let temp = arr[i];
               let j;
               for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
                   arr[j] = arr[j - gap];
               }
               arr[j] = temp;
           }
       }
       return arr;
   }
相关推荐
葫三生17 分钟前
如何评价《论三生原理》在科技界的地位?
人工智能·算法·机器学习·数学建模·量子计算
清幽竹客19 分钟前
vue-37(模拟依赖项进行隔离测试)
前端·vue.js
vvilkim19 分钟前
Nuxt.js 页面与布局系统深度解析:构建高效 Vue 应用的关键
前端·javascript·vue.js
滿23 分钟前
Vue3 父子组件表单滚动到校验错误的位置实现方法
前端·javascript·vue.js
夏梦春蝉1 小时前
ES6从入门到精通:模块化
前端·ecmascript·es6
拓端研究室2 小时前
视频讲解:门槛效应模型Threshold Effect分析数字金融指数与消费结构数据
前端·算法
工一木子3 小时前
URL时间戳参数深度解析:缓存破坏与前端优化的前世今生
前端·缓存
随缘而动,随遇而安4 小时前
第八十八篇 大数据中的递归算法:从俄罗斯套娃到分布式计算的奇妙之旅
大数据·数据结构·算法
半点寒12W5 小时前
微信小程序实现路由拦截的方法
前端
IT古董5 小时前
【第二章:机器学习与神经网络概述】03.类算法理论与实践-(3)决策树分类器
神经网络·算法·机器学习