前端排序算法大全:从冒泡到实战的趣味指南

24 阅读4分钟

❤ 写在前面
如果觉得对你有帮助的话,点个小❤❤ 吧,你的支持是对我最大的鼓励~
个人独立开发wx小程序,感谢支持! small.png


📊 排序,不就是排座位吗?

想象一下,你是一位班主任,需要给全班同学按身高排座位——这就是排序!在前端开发中,我们每天都在进行各种“排座位”操作:商品按价格排序、文章按时间排序、用户按姓名排序...

但你知道吗?排座位的方式有很多种,有的快速但混乱,有的稳定但慢速。今天我们就来探索前端开发中那些有趣的排序方式!

🎯 排序算法分类图

flowchart TD
    A[前端排序算法] --> B[基础排序算法]
    A --> C[高级排序算法]
    A --> D[JavaScript内置排序]
    
    B --> B1[冒泡排序]
    B --> B2[选择排序]
    B --> B3[插入排序]
    
    C --> C1[快速排序]
    C --> C2[归并排序]
    C --> C3[堆排序]
    
    D --> D1[Array.sort<br/>默认算法]
    D --> D2[自定义比较函数]

🔥 基础排序算法:三大经典招式

1. 冒泡排序 - “相邻交换法”

就像气泡从水底升到水面一样,每次比较相邻元素,把大的“冒”到后面。

// 冒泡排序实现
function bubbleSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i - 1; j++) {
      // 相邻元素比较,大的往后冒
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // ES6解构交换
      }
    }
  }
  return arr;
}

// 试试看!
console.log(bubbleSort([5, 3, 8, 1, 2])); // [1, 2, 3, 5, 8]

适用场景:教学演示、小数据量排序

2. 选择排序 - "选最小放前面"

每次找到最小的元素,放到已排序序列的末尾。

function selectionSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    let minIndex = i;
    // 找最小值的索引
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }
    // 把最小值放到前面
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
  }
  return arr;
}

3. 插入排序 - "扑克牌整理法"

就像整理扑克牌,每次把新牌插入到合适位置。

function insertionSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    let current = arr[i];
    let j = i - 1;
    // 向前找到合适位置插入
    while (j >= 0 && arr[j] > current) {
      arr[j + 1] = arr[j];
      j--;
    }
    arr[j + 1] = current;
  }
  return arr;
}

⚡ 高级排序算法:效率之选

快速排序 - "分而治之的王者"

选择一个基准,把小于基准的放左边,大于的放右边,然后递归处理。

function quickSort(arr) {
  if (arr.length <= 1) return arr;
  
  const pivot = arr[Math.floor(arr.length / 2)];
  const left = [];
  const right = [];
  const equal = [];
  
  for (let item of arr) {
    if (item < pivot) left.push(item);
    else if (item > pivot) right.push(item);
    else equal.push(item);
  }
  
  return [...quickSort(left), ...equal, ...quickSort(right)];
}

时间复杂度:平均O(n log n),最坏O(n²)

🚀 JavaScript内置排序:Array.sort()

这才是我们日常最常用的!但你知道它默认按字符串Unicode排序吗?

// 惊喜还是惊吓?
[10, 2, 1].sort(); // [1, 10, 2] 😱

// 正确方式:提供比较函数
[10, 2, 1].sort((a, b) => a - b); // [1, 2, 10] ✅

📈 排序算法选择流程图

flowchart TD
    Start[需要排序?] --> Condition1{数据量大小}
    
    Condition1 -- &#34;小数据量<br/>(< 100)&#34; --> C1[基础算法即可<br/>冒泡/选择/插入]
    Condition1 -- &#34;大数据量&#34; --> Condition2{是否需要稳定排序?}
    
    Condition2 -- &#34;是<br/>(相同值保持原顺序)&#34; --> C2[归并排序]
    Condition2 -- &#34;否&#34; --> Condition3{内存是否充足?}
    
    Condition3 -- &#34;充足&#34; --> C3[快速排序<br/>通常最快]
    Condition3 -- &#34;紧张&#34; --> C4[堆排序]
    
    C1 --> D[使用JavaScript的<br/>Array.sort<br/>V8引擎自动优化]
    C2 --> D
    C3 --> D
    C4 --> D
    
    D --> End[完成排序!🎉]

💡 实战应用场景

场景1:电商商品排序

// 按价格排序
products.sort((a, b) => a.price - b.price);

// 多条件排序:先按销量,再按评分
products.sort((a, b) => {
  if (a.sales !== b.sales) {
    return b.sales - a.sales; // 销量降序
  }
  return b.rating - a.rating; // 评分降序
});

场景2:表格动态排序

// 可配置的表格排序
function sortTable(data, key, direction = 'asc') {
  return [...data].sort((a, b) => {
    const aVal = a[key];
    const bVal = b[key];
    
    if (direction === 'asc') {
      return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
    } else {
      return aVal > bVal ? -1 : aVal < bVal ? 1 : 0;
    }
  });
}

场景3:中文排序

// 中文按拼音排序
const chineseNames = ['张三', '李四', '王五'];
chineseNames.sort((a, b) => 
  a.localeCompare(b, 'zh-CN')
);

🎨 可视化排序过程(有趣实现)

// 动画演示冒泡排序
async function visualBubbleSort(arr, updateUI) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i - 1; j++) {
      // 高亮比较的元素
      updateUI(arr, { comparing: [j, j + 1] });
      await delay(300); // 暂停一下,让用户看清
      
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
        // 更新UI显示交换
        updateUI(arr, { swapping: [j, j + 1] });
        await delay(300);
      }
    }
  }
  updateUI(arr, { sorted: true });
}

📊 性能对比表

算法平均时间复杂度最佳情况最坏情况是否稳定使用场景
冒泡排序O(n²)O(n)O(n²)教学、小数据
选择排序O(n²)O(n²)O(n²)小数据量
插入排序O(n²)O(n)O(n²)近乎有序的数据
快速排序O(n log n)O(n log n)O(n²)通用、大数据
归并排序O(n log n)O(n log n)O(n log n)需要稳定排序
Array.sortO(n log n)O(n log n)O(n log n)日常开发

🏆 总结与建议

  1. 日常开发:直接用 Array.sort(),现代JavaScript引擎已经高度优化
  2. 面试准备:理解各种排序原理,能手写1-2种即可
  3. 特殊需求:根据数据特点选择合适算法
  4. 性能关键:大数据量时,优先考虑快速排序或归并排序

记住,最好的排序算法不一定是理论上最快的,而是最适合你当前场景的!


彩蛋:试试这个"睡眠排序"(仅供娱乐,切勿生产使用!):

// 绝对不要在工作中使用这个!
function sleepSort(arr) {
  arr.forEach(num => {
    setTimeout(() => console.log(num), num * 10);
  });
}

希望这篇博客让你对前端排序有了新的认识!在实际开发中,理解原理比死记硬背更重要。Happy coding! 🚀


点赞收藏这篇博客,下次面试被问到排序算法时,你就是最靓的仔!