JavaScript 五大基础排序算法原理与代码实现

作者:木棉时间:2026-10-24 03:54:07浏览:147

本文详细解析前端面试中常见的五种基础排序算法:插入排序、选择排序、归并排序、冒泡排序及快速排序。通过动画演示与实例讲解,深入阐述各算法的核心原理、编程思路及时间复杂度,并提供完整的 JavaScript 实现代码,帮助开发者掌握排序逻辑并应对技术面试。

本文详细介绍 JavaScript 前端开发中必备的基础排序算法原理及其具体实现方法,供读者参考学习。

排序算法是技术面试与笔试中的高频考点。本文将通过动画演示直观展示排序过程,结合具体实例进行讲解,并最后提供完整的 JavaScript 版本排序算法代码。

插入排序

插入排序

算法核心逻辑如下: 1. 初始状态下,认为数组的第一个元素已处于排序状态。 2. 依次取出下一个未排序的元素,在已排序的元素序列中从后向前进行扫描。 3. 若已排序的元素大于新取出的元素,则将已排序元素向后移动一位。 4. 重复步骤 3,直到找到已排序元素小于或等于新元素的位置。 5. 将新元素插入到该位置之后。 6. 重复步骤 2 至 5,直至所有元素处理完毕。

示例数组设定为:arr = [5, 6, 3, 1, 8, 7, 2, 4]


[5] 6 3 1 8 7 2 4 //第一个元素被认为已经被排序

[5,6] 3 1 8 7 2 4 //6与5比较,放在5的右边

[3,5,6] 1 8 7 2 4 //3与6和5比较,都小,则放入数组头部

[1,3,5,6]  8 7 2 4 //1与3,5,6比较,则放入头部

[1,3,5,6,8]  7 2 4

[1,3,5,6,7,8] 2 4

[1,2,3,5,6,7,8] 4

[1,2,3,4,5,6,7,8] 

编程实现思路:采用双层循环结构。外循环负责遍历未排序部分的元素,内循环处理已排序部分。将未排序元素作为标杆值,与已排序元素逐一比较;若标杆值较小则交换位置,否则保持当前位置不动。


function insertSort(arr){
  var tmp;
  for(var i=1;i<arr.length;i++){
    tmp = arr[i];
    for(var j=i;j>=0;j--){
      if(arr[j-1]>tmp){
        arr[j]=arr[j-1];
      }else{
        arr[j]=tmp;
        break;
      }
    }
  }
  return arr
}

该算法的时间复杂度为 O(n^2)。

选择排序

插入排序

算法描述:直接从待排序数组中选取最小(或最大)的数字,将其放置到新数组的相应位置。


[1] 5 6 3 8 7 2 4 
[1,2] 5 6 3 8 7 4 
[1,2,3] 5 6 8 7 2 4 
[1,2,3,4] 5 6 8 7
[1,2,3,4,5] 6 8 7 
[1,2,3,4,5,6] 8 7 
[1,2,3,4,5,6,7] 8 
[1,2,3,4,5,6,7,8] 

编程实现思路:首先假设第一个元素为最小值,通过循环遍历找出实际的最小元素,并将其与第一个元素交换位置。随后假设第二个元素为最小值,重复上述操作,直至完成排序。


function selectSort(array) {
 var length = array.length,
   i,
   j,
   minIndex,
   minValue,
   temp;
 for (i = 0; i < length - 1; i++) {
  minIndex = i;
  minValue = array[minIndex];
  for (j = i + 1; j < length; j++) {//通过循环选出最小的
   if (array[j] < minValue) {
    minIndex = j;
    minValue = array[minIndex];
   }
  }
  // 交换位置
  temp = array[i];
  array[i] = minValue;
  array[minIndex] = temp;
 }
 return array
}

该算法的时间复杂度为 O(n^2)。

归并排序

插入排序

算法描述: 1. 将 n 个记录视为 n 个长度为 1 的有序子表。 2. 进行两两归并操作,使记录关键字有序,得到 n/2 个长度为 2 的有序子表。 3. 重复第 2 步操作,直到所有记录归并成一个长度为 n 的完整有序表。


5 6 3 1 8 7 2 4

[5,6] [3,1] [8,7] [2,4]

[5,6] [1,3] [7,8] [2,4]

[5,6,1,3] [7,8,2,4]

[1,3,5,6] [2,4,7,8]

[1,2,3,4,5,6,7,8]

编程实现思路:采用分治策略,将数组不断等分为两半,递归处理后再进行合并操作。


function merge(left, right) {
 var tmp = [];

 while (left.length && right.length) {
  if (left[0] < right[0])
   tmp.push(left.shift());
  else
   tmp.push(right.shift());
 }

 return tmp.concat(left, right);
}

function mergeSort(a) {
 if (a.length === 1) 
  return a;

 var mid = Math.floor(a.length / 2)
  , left = a.slice(0, mid)
  , right = a.slice(mid);

 return merge(mergeSort(left), mergeSort(right));
}

该算法的时间复杂度为 O(nlogn)。

快速排序

插入排序

算法描述:

  1. 在数据集中选择一个元素作为“基准”(pivot)。
  2. 执行分区(partition)操作:将所有小于基准的元素移至基准左侧,所有大于基准的元素移至基准右侧。分区结束后,基准元素即处于最终排序后的正确位置。
  3. 对基准左侧和右侧的两个子集,递归重复上述第一步和第二步操作,直到所有子集仅包含一个元素为止。

5 6 3 1 8 7 2 4

pivot
|
5 6 3 1 9 7 2 4
|
storeIndex

5 6 3 1 9 7 2 4//将5同6比较,大于则不更换
|
storeIndex

3 6 5 1 9 7 2 4//将5同3比较,小于则更换
 |
 storeIndex

3 6 1 5 9 7 2 4//将5同1比较,小于则不更换
  |
  storeIndex
...

3 6 1 4 9 7 2 5//将5同4比较,小于则更换
   |
   storeIndex

3 6 1 4 5 7 2 9//将标准元素放到正确位置
   |
storeIndex pivot

上述逻辑阐述了分区过程,接下来需对每个子区间执行相同操作。


function quickSort(arr){
  if(arr.length<=1) return arr;
  var partitionIndex=Math.floor(arr.length/2);
  var tmp=arr[partitionIndex];
  var left=[];
  var right=[];
  for(var i=0;i<arr.length;i++){
    if(arr[i]<tmp){
      left.push(arr[i])
    }else{
      right.push(arr[i])
    }
  }
  return quickSort(left).concat([tmp],quickSort(right))
}

上述版本在极端情况下可能导致堆栈溢出,因此建议使用优化后的版本。

原地分区版:主要区别在于先执行分区处理,将数组划分为左小右大的两部分,从而优化空间使用。


function quickSort(arr){
  function swap(arr,right,left){
    var tmp = arr[right];
    arr[right]=arr[left];
    arr[left]=tmp;
  }
  function partition(arr,left,right){//分区操作,
    var pivotValue=arr[right]//最右面设为标准
    var storeIndex=left;
    for(var i=left;i<right;i++){
      if(arr[i]<=pivotValue){
        swap(arr,storeIndex,i);
        storeIndex++;
      }
    }
    swap(arr,right,storeIndex);
    return storeIndex//返回标杆元素的索引值
  }
  function sort(arr,left,right){
    if(left>right) return;
    var storeIndex=partition(arr,left,right);
    sort(arr,left,storeIndex-1);
    sort(arr,storeIndex+1,right);
  }
  sort(arr,0,arr.length-1);
  return arr;
}

该算法的平均时间复杂度为 O(nlogn)。

冒泡排序

插入排序

算法描述: 1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 3. 针对所有的元素重复以上的步骤,除了最后一个。 4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。5.


5 6 3 1 8 7 2 4

[5 6] 3 1 8 7 2 4 //比较5和6

5 [6 3] 1 8 7 2 4

5 3 [6 1] 8 7 2 4

5 3 1 [6 8] 7 2 4

5 3 1 6 [8 7] 2 4

5 3 1 6 7 [8 2] 4

5 3 1 6 7 2 [8 4]

5 3 1 6 7 2 4 8 // 这样最后一个元素已经在正确位置,所以下一次开始时候就不需要再比较最后一个

编程实现思路:外循环控制需要比较的元素范围(例如第一次排序后,最后一个元素无需再比较),内循环负责两两元素比较,将元素放置到正确位置。


function bubbleSort(arr){
  var len=arr.length;
  for(var i=len-1;i>0;i--){
    for(var j=0;j<i;j++){
      if(arr[j]>arr[j+1]){
        var tmp = arr[j];
        arr[j]=arr[j+1];
        arr[j+1]=tmp
      }
    }
  }
  return arr;
}

该算法的时间复杂度为 O(n^2)。

感兴趣的朋友可以使用在线 HTML/CSS/JavaScript 代码运行工具:http://tools.jb51.net/code/HtmlJsRun 测试上述代码的运行效果。

PS:这里再为大家推荐一款关于排序的演示工具供大家参考:

在线动画演示插入/选择/冒泡/归并/希尔/快速排序算法过程工具: http://tools.jb51.net/aideddesign/paixu_ys

更多关于 JavaScript 相关内容感兴趣的读者可查看本站专题:《JavaScript 数学运算用法总结》、《JavaScript 数据结构与算法技巧总结》、《JavaScript 数组操作技巧总结》、《JavaScript 排序算法总结》、《JavaScript 遍历算法与技巧总结》、《JavaScript 查找算法技巧总结》及《JavaScript 错误与调试技巧总结》

希望本文所述内容对大家学习 JavaScript 程序设计有所帮助。

作者最新文章