CSS教程

关注公众号 jb51net

关闭
网页制作 > CSS > CSS教程 >

用CSS写一个可用的冒泡排序算法

wzkMaster

想象在一场面试中,面试官问你“你能实现冒泡排序吗?”,而你的回答是“当然可以,你要我用 JavaScript 实现还是 CSS?”

这多酷啊!

我知道你现在在想:“没有面试官会因为我做了一个模拟冒泡排序的动画而感到印象深刻”,你是对的!

但如果我们真的能用 CSS 写一个可用的冒泡排序算法,并且将其可视化展示,那就很不一样了!

下面我们就来看看如何实现。

Demo

使用方法::root 选择器下有五个值

:root {
  --val1: 12;
  --val2: 16;
  --val3: 9;
  --val4: 14;
  --val5: 7;
}

它们对应了我们要排序的数组。上面的五个值代表了 [12, 16, 9, 14, 7]

你可以改变这些数字(0 到 20 之间的任意值),然后点击“运行”,程序就会自动为你完成排序。

注意:在手机上最后的几下动画可能不会展示并出现页面白屏,在电脑上你的风扇可能会响起来。

这是使用大量依赖于前置结果的计算带来的后果,我不确定这样会不会用尽内存,但我在这个项目中确实突破了 CSS 的极限!

总之,听完这些警告之后,你就可以试一试了(由于动画只播放一次,你可以点击“运行”按钮来再次运行动画)!

代码解释

听着,这段代码实际上很傻,所以我不打算做完整的讲解,但代码中有几个地方很有趣:

获取 v2 > v1 的布尔值结果

--is-1-greater-2-step-1: Min(1, Max(var(--arr1s0) - var(--arr2s0), 0));

这看起来很复杂,但实际上并不,这段代码做了下面这几件事:

还是感觉很困惑?这里是等价的 JS 代码:

let pos1 = 7;
let pos2 = 15;
let diff1and2 = pos1 - pos2;
// 如果 diff1and2 是负数,下一步会把它变成 0
let OneGreaterOrZero = Math.max(diff1and2, 0);
let result = Math.min(1, OneGreaterOrZero);
console.log(diff1and2, OneGreaterOrZero, result); // result 总是 0 或 1,分别代表 false / true

交换数组位置

那么我们怎么交换数组中的元素位置呢?

为了实现冒泡排序,我们需要在第一个值大于第二个值时交换两个值。

我们没法像在 JS 中一样使用中间变量这样的魔法。但下面这段代码可以帮我们实现:

--arr1s1: calc(
  var(--is-2-greater-1-step-1) * var(--arr1s0) + var(--is-1-greater-2-step-1) *
    var(--arr2s0)
);
--arr2s1: calc(
  var(--is-1-greater-2-step-1) * var(--arr1s0) + var(--is-2-greater-1-step-1) *
    var(--arr2s0)
);

这段代码看起来也非常复杂,但它实际上非常简单。

在刚刚的“函数”中,我们得到了一个代表 1 和 2 之间大小关系的布尔值,所以我们在这里可以得到 1 或者 0。

我们也可以很简单地获得其反转值:

--is-2-greater-1-step-1: (1 - var(--is-1-greater-2-step-1));

这段代码的美妙之处在于我们可以使用下面的技巧:

// 假设这是我们要排序的数组
origArray = [7, 2];
// 我们运行刚刚的两个函数得到下面两个变量
oneIsGreater = 1;
twoIsGreater = 0;
// 我们现在可以把这两个值乘在一起。 如果 [2] 更大的话我们还是返回原始值. 但如果 [1] 比 [2] 大的话我们就交换它们的值。
newArray[0] = twoIsGreater * origArray[0] + oneIsGreater * origArray[1];
newArray[1] = oneIsGreater * origArray[0] + twoIsGreater * origArray[1];
// 这等价于
newArray[0] = 0 * 7 + 1 * 2; //2
newArray[1] = 1 * 7 + 0 * 2; //7

如果将 oneIsGreater 和 twoIsGreater 互换,则我们得到仍是原来的值!

origArray = [7, 2];
oneIsGreater = 0;
twoIsGreater = 1;
// 一样的“函数”
newArray[0] = twoIsGreater * origArray[0] + oneIsGreater * origArray[1];
newArray[1] = oneIsGreater * origArray[0] + twoIsGreater * origArray[1];
// 等价于:
newArray[0] = 1 * 7 + 0 * 2; //7
newArray[1] = 0 * 7 + 1 * 2; //2

这就是我们进行冒泡排序所需的全部功能!

之所以我写了一大堆 CSS 代码,是因为我们在 CSS 中(暂时)还无法使用循环。所以我们必须手动地写出冒泡排序中的每一步交换:

就这些了!

正如我所说的,这篇文章并不是一篇完整的教程。但我确实想介绍这些有趣的用 CSS 实现的 "开关" 和 "布尔值",它们可能会在未来你遇到的的某些奇怪场景中派上用场!

以上就是用CSS写一个可用的冒泡排序算法的详细内容,更多关于CSS冒泡排序的资料请关注脚本之家其它相关文章!