6

JavaScript冒泡排序+Vue可视化冒泡动画 - 安木夕

 2 years ago
source link: https://www.cnblogs.com/anding/p/16989579.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
1.gif

冒泡排序(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]则交换值位置。
  • 、如下图,依次相邻元素比较、交换,一轮完成后,最大元素就到了最右边了。这个过程中,最大的元素(最大的泡泡)就像冒泡一样到了末尾。
image
  • ③、然后继续对剩下的前面len-1=5个元素重复上述步骤,直到只剩下一个元素。这是一个递归的过程,递归到第一个元素,就完成了冒泡排序。

image

冒泡排序的动画过程如下图,排序过程很直观,一目了然,下一章节也实现一个跟好的。

151257-20221217212826597-555262192.gif

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;}

泡泡列表展示效果如下:

image.png
  • 然后就是排序过程了,对排序对象集合进行遍历,把每一次排序操作包装成一个(闭包)函数,放到一个集合里,后面就可自定义调用执行了。
  • 先是用集合实现了一遍,发现这个场景用迭代器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>组件来实现。
  • “单步执行”就是点击一次只执行一步,“自动执行”则会自动顺序执行。
  • 修改参数后需”重置“进行初始化。

手动单步执行效果:

1.gif

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

点击查看【juejin】


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


Recommend

  • 34
    • blog.csdn.net 6 years ago
    • Cache

    漫画:什么是冒泡排序?

  • 32

    对于编程算法,可能很多读者在学校第一个了解的就是冒泡排序,但是你真的知道 Python 内建排序算法list.sort() 的原理吗?它使用的是一种快速、稳定的排序算法Timsort,其时间复杂度为 O(n log n),该算法的目标在于处理大规模真实数据。...

  • 40
    • studygolang.com 6 years ago
    • Cache

    Go实现冒泡排序

    排序:排序是将一组数据,按照一定的顺序进行排列的过程。 排序分类: 内部排序:指将需要处理的所有数据都加载到内存存储器中进行排序。包括(交换式排序法、选择式排序法和插入式排序法)。 外部排序法: 数...

  • 61
    • www.tuicool.com 5 years ago
    • Cache

    冒泡排序深入理解

    冒泡排序深入理解 对于冒泡排序有一个小性质: 每一次都会把序列未排好序的最大数"沉底", 即推到序列尾部 1. P4378 Out of Sorts S 留意着农场之外...

  • 29
    • www.tuicool.com 5 years ago
    • Cache

    排序--冒泡排序

    1、什么是冒泡排序? 就是把一个无序数组内的元素,从头开始,两两比较并交换位置,直到把最大(最小)的一位放置在队尾 2、代码原理...

  • 11

    交换排序 一:冒泡排序 交换排序的定义: 交换交换,换的是两个元素的位置,根据序列中,两个元素关键字的比较结果,对两个元素在序列中的位置进行交换。 交换排序,最常见的就是冒泡排序和...

  • 22
    • www.cnblogs.com 4 years ago
    • Cache

    Python 算法之冒泡排序

    冒泡排序基本思想 对于列表a依次比较两个相邻元素的大小,若a[j]大于a[j+1]则进行交换,第一趟把最大的数换到最后,依次类推生成有序的列表。 N个元素的列表要排序完成,需N-1趟排序(例:如果N是3(a = [...

  • 4

    缘起 最近阅读<<我的第一本算法书>>(【日】石田保辉;宫崎修一) 本系列笔记拟采用golang练习之 冒泡排序 冒泡排序就是重复“从序列右边开始比较相邻两个数字的大小, 再根据结果交换两个数...

  • 7
    • www.cxyxiaowu.com 3 years ago
    • Cache

    你的同龄人写不出冒泡排序

    你的同龄人写不出冒泡排序-五分钟学算法 当前位置:五分钟学算法 > 数据结构 > 你的同龄人写不出冒泡排序 ...

  • 5

    冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK