效果图
初始化页面
排序过程
结果
实现
实现可视化排序主要是分为三个步骤:
1.获取列表
2.对列表进行冒泡排序,并记录每次排序结果
3.使用setInterval函数每次间隔一段时间将排序结果按顺序显示出来,存在一定的时间间隔就实现了可视化排序
//点击排序按钮开始排序
document.getElementById("sort").onclick = function () {
list = getList();
list = doSort(list);
time = setInterval('renderSort(visibleArray)', 200);
}
获取列表
function getList() {
var list = [];
var i = 0;
while(li[i] != undefined) {
list.push(li[i].innerText);
i++;
}
listNum = list.length;
return list;
}
对列表进行冒泡排序,并记录每次排序结果
function doSort(list) {
//使用visibleArray数组来记录每次的排序结果(数组)
visibleArray = [];
for(var i = 0; i < list.length-1; i++) {
for(var j = i+1; j < list.length; j++) {
if(parseInt(list[i]) > parseInt(list[j])) {
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
visibleArray.push(list.slice());
}
}
}
ps:我在这里纠结了很久,因为一开始我往visibleArray里面添加数组的时候使用的是visibleArray.push(list)
,看似很合理,但是你会发现,在js中数组可是引用类型啊!所以排完序后,visibleArray里面的元素全都是一个样并且等于按升序的list。
我还尝试了函数传参的方式(不是说函数传参是按值传递吗!),于是又了下面这段代码
visibleArray[visibleArray.length] = (function(temp){
return temp;
})(list);
结果还是没变,因为尽管temp是按值传递的,但是它传递的值可是list指向的地址啊。(这样说传值也没错嘛)
所以,失败。
最后被我找到了解决方法visibleArray.push(list.slice());
我觉得这个还是很好解释的,因为list.slice()会创建一个新的数组,跟list一点关系都没有(你看list都没改变),把这个新的数组放入visibleArray就好啦。
使用setInterval函数每次间隔一段时间将排序结果按顺序显示出来
time = setInterval('renderSort(visibleArray)', 200);
可以看到每隔200毫秒就会执行renderSort函数,下面是renderSort函数
function render(list) {
ul.innerHTML = "";
var str;
console.log("render", list.length);
for(var i = 0; i < list.length; i++) {
str = "<li>"+list[i]+"</li>";
ul.innerHTML += str;
}
init();
}
function renderSort(visibleArray) {
if(visibleArray[renderNum] == undefined) {
clearInterval(time);
} else {
render(visibleArray[renderNum]);
renderNum++;
}
}
原理也很简单:就是把visibleArray里的所有排序结果都渲染一遍后就可以通过clearInterval来结束渲染了。
render函数就是将你传入的数组一个一个渲染到HTML上。
这里也遇到一个小问题,setInterval只执行一次。原因就是
time = setInterval('renderSort(visibleArray)', 200);
和
time = setInterval(renderSort(visibleArray), 200);
完全不一样啊喂!
上面那个才是正确写法。