JavaScript冒泡排序+Vue可视化冒泡动画
冒泡排序(Bubble Sort)算是前端最简单的算法,也是最经典的排序算法了。网上JavaScript版本的冒泡排序很多,今天用Vue实现一个动态的可视化冒泡排序。
01、JavaScript冒泡排序
冒泡排序原理也比较简单,就是相邻元素两两比较排序,把大的元素冒泡排序到后面,递归所有相邻元素组合完成排序。
1.1、原理
有一个无序数组:let arr = [100, 5, 6, 17, 3, 1]
,长度为len=6
。
- ①、从第一位元素100(0索引)开始,比较相邻
arr[0]、arr[1]
元素的大小,大的排后面,如果arr[0]>arr[1]
则交换值位置。 - ②、如下图,依次相邻元素比较、交换,一轮完成后,最大元素就到了最右边了。这个过程中,最大的元素(最大的泡泡)就像冒泡一样到了末尾。
- ③、然后继续对剩下的前面
len-1=5
个元素重复上述步骤,直到只剩下一个元素。这是一个递归的过程,递归到第一个元素,就完成了冒泡排序。
冒泡排序的动画过程如下图,排序过程很直观,一目了然,下一章节也实现一个跟好的。
1.2、JavaScript实现
经典冒泡排序算法,用两个for
循环来实现所有元素的两两对比排序。统计了一下排序次数,一共比较了15次。冒泡排序的时间复杂度是O(n^2),这是最大值,最小为O(n)。
//经典冒泡排序算法 //从小到大冒泡排序 let arr = [100, 5, 6, 17, 3, 1]; let count=0; //计数器 function bubbleSort(arr) { const len = arr.length; let t;count=0; for (let i = 0; i < len - 1; i++) { for (let j = 0; j < len - i - 1; j++) { count++; //比较相邻两个元素 if (arr[j] > arr[j + 1]) { //交换两个元素,大的往后排列 t = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = t; } } } return arr; } console.log(bubbleSort(arr),"比较次数:",count); //[1, 3, 5, 6, 17, 100] '比较次数:' 15
上面代码中交换两个元素位置的时候,用了一个中间变量(t),可以改进一下。用一个解构赋值来交换值,就不用额外的一个中间变量(t)了。
let arr = [100, 5, 6, 17, 3, 1]; function bubbleSort(arr) { const len = arr.length; for (let i = 0; i < len - 1; i++) { for (let j = 0; j < len - i - 1; j++) { //比较相邻两个元素 if (arr[j] > arr[j + 1]) { //用结构赋值进行交换 [arr[j], arr[j + 1]] = [arr[j+1], arr[j]]; } } } return arr; } console.log(bubbleSort(arr)); //[1, 3, 5, 6, 17, 100]
02、Vue实现一个冒泡动画
用Vue来实现一个可视化的冒泡排序,用Vue就不用去操作Dom了,只需要要处理好排序过程即可,因此首先要对排序过程进行改造。
2.1、排序过程改造
上一章节的排序是连续执行,瞬间完成的。要实现可视化的排序效果,每一个排序步骤之间得有间隔,给过渡动画留时间。就需要把排序的每一个步骤拆开,可以单独控制执行。
- 定义一个排序对象
SortItem
,包装待排序元素,用于可视化展示,属性包括排序值、泡泡大小、泡泡颜色。 - 用上面的排序对象
SortItem
,生成排序对象集合,正式排序步骤中用该集合。方法的参数为排序元素字符串,空格隔开,如“9 100 6 17 3 1”。
//定义一个排序对象,包装待排序元素 function SortItem(n) { this.value = n; this.size = 30 + n + 'px'; //泡泡大小,初试大小30px this.color = bubbleColor.default; } //生成排序对象集合,参数为排序元素字符串,如“9 100 6 17 3 1” function generateSortItems(arrStr) { let arrItems = []; let arr = arrStr.trim().split(' '); for (let i = 0; i < arr.length; i++) { arrItems[i] = new SortItem(window.parseInt(arr[i])); } return arrItems; }
泡泡列表展示效果如下:
- 然后就是排序过程了,对排序对象集合进行遍历,把每一次排序操作包装成一个(闭包)函数,放到一个集合里,后面就可自定义调用执行了。
- 先是用集合实现了一遍,发现这个场景用迭代器
Generator
更优雅,马上重构,上迭代器!每次迭代yield
返回排序的函数。
//迭代器实现排序步骤的拆分 function* generateSortFunc(items) { const len = items.length; for (let i = 0; i < len - 1; i++) { for (let j = 0; j < len - i - 1; j++) { //迭代器返回的是一个(闭包)函数,为每一个排序步骤 yield () => { //执行排序前重置泡泡颜色 resetColor(items); //正在排序的泡泡元素高亮 items[j].color = bubbleColor.inprocess; items[j + 1].color = bubbleColor.inprocess; if (items[j].value > items[j + 1].value) { [items[j], items[j + 1]] = [items[j + 1], items[j]]; } } } //完成一轮排序,末尾泡泡元素标记为完成态颜色 items[len - i - 1].color = bubbleColor.completed; } }
🔸什么是Generator?
- 她是一个迭代器,返回一个遍历器对象,符合可迭代协议和迭代器协议,可用
next()
、for(of)
迭代。 - 她是可控函数:内部代码可以自由控制暂停和继续执行。标准的函数是一次性执行完毕,直到末尾或
return
语句。而生成器的函数可以由yield
暂停执行(交出控制权),next()
恢复执行。 - 她是一个状态机,封装了多个内部状态。
- 她是异步任务管理容器,提供一种异步的实现方案。
Generator 使用一个特殊的函数语法function*
(带星*
号)创建生成器generator
,调用生成器函数获得一个生成器对象,该对象的实例方法:
实例方法 | 描述 |
---|---|
next() | 恢复执行,返回一个由 yield 表达式生成的值:{value: 1, done: false} |
return(value?) | 返回给定的值并结束生成器,可提前中止生成器。 |
throw() | 向生成器抛出一个错误,生成器内部如没处理则会中止 |
2.2、可视化排序
接下来就不难了,排序的执行就是调用执行器的next()
方法,如果返回对象的done
属性为true
,则表示迭代完成,否则继续迭代,执行排序函数。
//单步执行 play() { let next = this.sortFunc.next(); if (next.done) { this.sortItems.forEach(item => item.color = bubbleColor.completed); this.stop(); } else next.value(); },
<li>
元素来显示排序对象。- 移动动画用的Vue的
<transition-group>
组件来实现。 - “单步执行”就是点击一次只执行一步,“自动执行”则会自动顺序执行。
- 修改参数后需”重置“进行初始化。
手动单步执行效果:
自动执行或更多排序参数可以直接查看在线代码示例:掘金-代码(可视化冒泡),完整代码也在这里。
参考资料
©️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤