冒泡排序(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)。

  1. //经典冒泡排序算法
  2. //从小到大冒泡排序
  3. let arr = [100, 5, 6, 17, 3, 1];
  4. let count=0; //计数器
  5. function bubbleSort(arr) {
  6. const len = arr.length;
  7. let t;count=0;
  8. for (let i = 0; i < len - 1; i++) {
  9. for (let j = 0; j < len - i - 1; j++) {
  10. count++;
  11. //比较相邻两个元素
  12. if (arr[j] > arr[j + 1]) {
  13. //交换两个元素,大的往后排列
  14. t = arr[j];
  15. arr[j] = arr[j + 1];
  16. arr[j + 1] = t;
  17. }
  18. }
  19. }
  20. return arr;
  21. }
  22. console.log(bubbleSort(arr),"比较次数:",count);
  23. //[1, 3, 5, 6, 17, 100] '比较次数:' 15

上面代码中交换两个元素位置的时候,用了一个中间变量(t),可以改进一下。用一个解构赋值来交换值,就不用额外的一个中间变量(t)了。

  1. let arr = [100, 5, 6, 17, 3, 1];
  2. function bubbleSort(arr) {
  3. const len = arr.length;
  4. for (let i = 0; i < len - 1; i++) {
  5. for (let j = 0; j < len - i - 1; j++) {
  6. //比较相邻两个元素
  7. if (arr[j] > arr[j + 1]) {
  8. //用结构赋值进行交换
  9. [arr[j], arr[j + 1]] = [arr[j+1], arr[j]];
  10. }
  11. }
  12. }
  13. return arr;
  14. }
  15. console.log(bubbleSort(arr));
  16. //[1, 3, 5, 6, 17, 100]

02、Vue实现一个冒泡动画

用Vue来实现一个可视化的冒泡排序,用Vue就不用去操作Dom了,只需要要处理好排序过程即可,因此首先要对排序过程进行改造。

2.1、排序过程改造

上一章节的排序是连续执行,瞬间完成的。要实现可视化的排序效果,每一个排序步骤之间得有间隔,给过渡动画留时间。就需要把排序的每一个步骤拆开,可以单独控制执行。

  • 定义一个排序对象SortItem,包装待排序元素,用于可视化展示,属性包括排序值、泡泡大小、泡泡颜色。
  • 用上面的排序对象SortItem,生成排序对象集合,正式排序步骤中用该集合。方法的参数为排序元素字符串,空格隔开,如“9 100 6 17 3 1”。
  1. //定义一个排序对象,包装待排序元素
  2. function SortItem(n) {
  3. this.value = n;
  4. this.size = 30 + n + 'px'; //泡泡大小,初试大小30px
  5. this.color = bubbleColor.default;
  6. }
  7. //生成排序对象集合,参数为排序元素字符串,如“9 100 6 17 3 1”
  8. function generateSortItems(arrStr) {
  9. let arrItems = [];
  10. let arr = arrStr.trim().split(' ');
  11. for (let i = 0; i < arr.length; i++) {
  12. arrItems[i] = new SortItem(window.parseInt(arr[i]));
  13. }
  14. return arrItems;
  15. }

泡泡列表展示效果如下:

  • 然后就是排序过程了,对排序对象集合进行遍历,把每一次排序操作包装成一个(闭包)函数,放到一个集合里,后面就可自定义调用执行了。
  • 先是用集合实现了一遍,发现这个场景用迭代器Generator更优雅,马上重构,上迭代器!每次迭代yield返回排序的函数。
  1. //迭代器实现排序步骤的拆分
  2. function* generateSortFunc(items) {
  3. const len = items.length;
  4. for (let i = 0; i < len - 1; i++) {
  5. for (let j = 0; j < len - i - 1; j++) {
  6. //迭代器返回的是一个(闭包)函数,为每一个排序步骤
  7. yield () => {
  8. //执行排序前重置泡泡颜色
  9. resetColor(items);
  10. //正在排序的泡泡元素高亮
  11. items[j].color = bubbleColor.inprocess;
  12. items[j + 1].color = bubbleColor.inprocess;
  13. if (items[j].value > items[j + 1].value) {
  14. [items[j], items[j + 1]] = [items[j + 1], items[j]];
  15. }
  16. }
  17. }
  18. //完成一轮排序,末尾泡泡元素标记为完成态颜色
  19. items[len - i - 1].color = bubbleColor.completed;
  20. }
  21. }

什么是Generator?

  • 她是一个迭代器,返回一个遍历器对象,符合可迭代协议和迭代器协议,可用next()for(of)迭代。
  • 她是可控函数:内部代码可以自由控制暂停和继续执行。标准的函数是一次性执行完毕,直到末尾或return语句。而生成器的函数可以由yield暂停执行(交出控制权),next()恢复执行。
  • 她是一个状态机,封装了多个内部状态。
  • 她是异步任务管理容器,提供一种异步的实现方案。

Generator 使用一个特殊的函数语法function*(带星*号)创建生成器generator,调用生成器函数获得一个生成器对象,该对象的实例方法:

实例方法 描述
next() 恢复执行,返回一个由 yield表达式生成的值:{value: 1, done: false}
return(value?) 返回给定的值并结束生成器,可提前中止生成器。
throw() 向生成器抛出一个错误,生成器内部如没处理则会中止

2.2、可视化排序

接下来就不难了,排序的执行就是调用执行器的next()方法,如果返回对象的done属性为true,则表示迭代完成,否则继续迭代,执行排序函数。

  1. //单步执行
  2. play() {
  3. let next = this.sortFunc.next();
  4. if (next.done) {
  5. this.sortItems.forEach(item => item.color = bubbleColor.completed);
  6. this.stop();
  7. }
  8. else
  9. next.value();
  10. },
  • <li>元素来显示排序对象。
  • 移动动画用的Vue的<transition-group>组件来实现。
  • “单步执行”就是点击一次只执行一步,“自动执行”则会自动顺序执行。
  • 修改参数后需”重置“进行初始化。

手动单步执行效果:

自动执行或更多排序参数可以直接查看在线代码示例:掘金-代码(可视化冒泡),完整代码也在这里。

点击查看【juejin】


参考资料


️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀

JavaScript冒泡排序+Vue可视化冒泡动画的更多相关文章

  1. 冒泡动画按钮的简单实现(使用CSS3)

    冒泡动画按钮的简单实现(使用CSS3) 原始的参考文章是 http://tutorialzine.com/2010/10/css3-animated-bubble-buttons/ ,基本原理是利用了 ...

  2. Vue 中的动画特效

    Vue 中的动画特效 CSS 实现标签显隐 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  3. VUE:过渡&动画

    VUE:过渡&动画 vue动画的理解 1)操作css的 trasition 或 animation 2)vue会给目标元素添加/移除特定的class 3)过渡的相关类名 xxx-enter-a ...

  4. Vue过渡与动画

    通过 Vue.js 的过渡系统,可以在元素从 DOM 中插入或移除时自动应用过渡效果.Vue.js 会在适当的时机为你触发 CSS 过渡或动画,你也可以提供相应的 JavaScript 钩子函数在过渡 ...

  5. vue.js过度&动画、混入&插件

    1.vue  过度动画 1.过度 Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果.Vue 提供了内置的过渡封装组件,该组件用于包裹要实现过渡效果的组件. 语法格式: < ...

  6. Vue学习之动画小结(六)

    一.Vue中实现动画的方式:https://cn.vuejs.org/v2/guide/transitions.html Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果.包括 ...

  7. (尚014)Vue过渡与动画

    操作元素时有个过渡或动画的效果(渐变和移动的效果和放大缩小的效果) 过渡:trasition 动画:animation 1.vue动画的理解 1)操作css的trasition或animation(它 ...

  8. Vue过渡和动画效果展示(案例、GIF动图演示、附源码)

    前言 本篇随笔主要写了Vue过渡和动画基础.多个元素过渡和多个组件过渡,以及列表过渡的动画效果展示.详细案例分析.GIF动图演示.附源码地址获取. 作为自己对Vue过渡和动画效果知识的总结与笔记. 因 ...

  9. javascript实现汉诺塔动画效果

    javascript实现汉诺塔动画效果 当初以为不用html5也很简单,踩了javascript单线程的大坑后终于做出来了,没事可以研究下,对理解javascript的执行过程还是很有帮助的,代码很烂 ...

  10. javascript仿天猫加入购物车动画效果

    javascript仿天猫加入购物车动画效果   注意:首先需要声明的是:代码原思路不是我写的,是在网上找的这种效果,自己使用代码封装了下而已:代码中都有注释,我们最主要的是理解抛物线的思路及在工作中 ...

随机推荐

  1. MySQL学习(1)---MySQL概述

    什么是数据库 概述 数据库(Database)是长期存储在计算机内有组织.大量.共享的数据集合.它可以供各种用户共享,具有最小冗余度和较高的数据独立性.数据库管理系统DBMS(Database Man ...

  2. sql limit函数

    select * from <表名> order by <列名> desc limit <第几位数>; select * from villa_info order ...

  3. 2021 CCPC 威海站 VP记录(题解)

    2021 CCPC 威海站 VP记录(题解) 题目顺序为vp时开题顺序: A - Goodbye, Ziyin! 签到,连边数小于等于2的可以作为二叉树根,若有大于4的直接输出0. code: voi ...

  4. 齐博x1如何调试查找全站的表单提交接口参数

    H5.PC.WAP端的所有提交POST表单操作都是可以当作接口来用的. 比如我们通过PC或WAP浏览器打开相应要修改的界面,然后浏览器进入开发者模式,就可以追踪到所提交的变量参数.你在APP里边只要指 ...

  5. python: m个位置,每个位置有n种可能,求所有排列结果

    >>> import itertools >>> m, n = 3, 2 >>> paths = list(itertools.product(r ...

  6. vue中push()和splice()的使用方法

    vue中push()和splice()的使用方法 push()使用 push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度.注意:1. 新元素将添加在数组的末尾. 2.此方法改变数组的长度 ...

  7. 苹果 App Store 开始支持隐藏上架应用:只能通过链接下载

      据MacRumors报道,苹果公司最近宣布,正如其开发者网站上所概述的那样,App Store现在支持只能通过直接链接才能发现的隐藏应用.   图片来自 Apple 拥有不适合公开发布的应用的开发 ...

  8. ISCTF2022WP

    ISCTF2022改名叫套CTF吧(bushi),博主菜鸡一个,套题太多,挑一些题写下wp,勿喷. MISC 可爱的emoji   下载下来是个加密压缩包,根据hint掩码爆破密码 得到密码:KEYI ...

  9. FastApi学习1

    先写路由文件: 其次通过ORM操作数据库相关:

  10. Django的简单使用

    Django 基础简介 基础简介 1. 软件框架 一个公司是由公司中的各部部门来组成的,每一个部门拥有特定的职能,部门与部门之间通过相互的配合来完成让公司运转起来. 一个软件框架是由其中各个软件模块组 ...