想象在一场面试中,面试官问你“你能实现冒泡排序吗?”,而你的回答是“当然可以,你要我用 JavaScript 实现还是 CSS?”
这多酷啊!
我知道你现在在想:“没有面试官会因为我做了一个模拟冒泡排序的动画而感到印象深刻”,你是对的!
但如果我们真的能用 CSS 写一个可用的冒泡排序算法,并且将其可视化展示,那就很不一样了!
下面我们就来看看如何实现
Demo
使用方法::root
选择器下有五个值
|
|
它们对应了我们要排序的数组。上面的五个值代表了 [12, 16, 9, 14, 7]
。
你可以改变这些数字(0 到 20 之间的任意值),然后点击“运行”,程序就会自动为你完成排序。
**注意:**在手机上最后的几下动画可能不会展示并出现页面白屏,在电脑上你的风扇可能会响起来。
这是使用大量依赖于前置结果的计算带来的后果,我不确定这样会不会用尽内存,但我在这个项目中确实突破了 CSS 的极限!
总之,有了这些警告,你就可以试一试了(由于动画只播放一次,你可可以点击“运行”按钮来再次运行动画)!
代码解释
听着,这实际上很傻,所以我不打算做一个完整的教程,但有代码中几件事很有趣:
获取 v2 > v1 的布尔值结果
|
|
看起来很复杂,但实际上并不会,这段代码做了下面这几件事:
- 用数组第一位的值减去第二位的值。(为方便起见,我们称之为 “diff1and2”)。
- 求出 “diff1and2” 和 0 的最大值。我们这样做是希望: “如果 1 大于 2,我们会得到一个正值,但如果 2 大于 1,我们会得到 0”。我们把这个结果称为 “OneGreaterOrZero”。
- 然后,我们取 “OneGreaterOrZero”,并使用
Min
来确保它不大于 1。因此,如果 “OneGreaterOrZero” 是 6,我们将把它减为 1,但如果是 0,我们将返回 0。
还是感觉很困惑?这里是等价的 JS 代码:
|
|
交换数组位置
那么我们怎么交换数组中的元素位置呢?
为了实现冒泡排序,我们需要在第一个值大于第二个值时交换两个值。
我们没法像在 JS 中一样使用中间变量这样的魔法。
下面这段代码的可以帮我们实现:
|
|
这段代码看起来也非常复杂,但它实际上非常简单。
在刚刚的“函数”中,我们得到了一个代表 1 和 2 之间大小关系的布尔值,所以我们在这里可以得到 1 或者 0.
我们也可以很简单地获得其反转值:
|
|
这段代码的美妙之处在于我们可以使用下面的技巧:
|
|
如果将 oneIsGreater 和 twoIsGreater 互换,则我们得到仍是原来的值!
|
|
这就是我们进行冒泡排序所需的全部功能!
之所以我们写了一大堆 CSS 代码,是因为我们在 CSS 中(暂时)还无法使用循环。所以我们必须手动地写出冒泡排序中的每一步交换:
- 检查第 1 个数和第 2 个数,如果需要交换则交换位置
- 检查第 2 个数和第 3 个数,如果需要交换则交换位置
- 检查第 3 个数和第 4 个数,如果需要交换则交换位置
- 检查第 4 个数和第 5 个数,如果需要交换则交换位置
- 检查第 1 个数和第 2 个数,如果需要交换则交换位置
- 检查第 2 个数和第 3 个数,如果需要交换则交换位置
- 检查第 3 个数和第 4 个数,如果需要交换则交换位置
- 检查第 1 个数和第 2 个数,如果需要交换则交换位置
- 检查第 2 个数和第 3 个数,如果需要交换则交换位置
- 检查第 1 个数和第 2 个数,如果需要交换则交换位置
就这些了!
正如我所说的,不是一个完整的教程。但我确实想介绍这些有趣的用 CSS 实现的 “开关” 和 “布尔值”,它们可能会在未来你遇到的的某些奇怪场景中派上用场!
希望你们喜欢我的傻气。
现在,我只等着有人来让我实现冒泡排序,这样我就可以用我的 CSS 怪招来对付他们了!🤣💗