在《深入浅出node》中看到了这个问题,感觉很有趣,那就写一个吧!效果如图:
我们先来实现一个简单的冒泡排序:
const arrLength = 10
const arrRange = 30
const generateArr = () => {
return Array.from({ length: arrLength }).map(() =>
Math.floor(Math.random() * arrRange)
)
}
const compare = (x, y) => x - y
const swap = (a, i, j) => {
a[i] ^= a[j]
a[j] ^= a[i]
a[i] ^= a[j]
}
const bubbleSort = a => {
const len = a.length
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (compare(a[j], a[j + 1]) > 0) {
swap(a, j, j + 1)
}
}
}
}
const arr = generateArr()
console.log(arr)
bubbleSort(arr)
console.log(arr)
复制代码
接下来实现一个图表:
const generateChart = () => {
const block = document.querySelector('#sort')
block.style.width = `${arrLength * (pillarGap + pillarWidth)}px`
for (let i = 0; i < arrLength; i++) {
const newDiv = document.createElement('div')
Object.assign(newDiv.style, {
height: `${((arr[i] / arrRange) * 100).toFixed(0)}%`,
width: `${pillarWidth}px`,
marginLeft: `${pillarGap}px`
})
newDiv.innerText = arr[i]
block.append(newDiv)
}
}
复制代码
排序中主要变化是交换,再写一个交换元素的函数:
function exchange(el1, el2) {
var ep1 = el1.parentNode,
ep2 = el2.parentNode,
index1 = Array.prototype.indexOf.call(ep1.children, el1),
index2 = Array.prototype.indexOf.call(ep2.children, el2)
ep2.insertBefore(el1, ep2.children[index2])
ep1.insertBefore(el2, ep1.children[index1])
}
复制代码
最后我们只要把 bubbleSort
变为异步调用即可:
const bubbleSort = async a => {
const len = a.length
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
await swapTransform(a, j, j + 1, compare(a[j], a[j + 1]) > 0)
}
}
return a
}
复制代码
全部代码在我的GitHub上: github.com/wen98y/work… 欢迎 Star
这个花了2个多小时写完的,还是有些收获:
- 多关注js原生操作DOM
- async 的运用
- css运算符优先级
也有不足之处:这里交换很生硬,没有渐变的动画,我想的是用transform来写,但最后还是没想出来,如果各位有高招,欢迎评论。
还有用原生js撸代码是真的爽!