JavaScript排序非常快。如果我們可以用肉眼看到它的實現過程,我首先想到的是減慢排序。每個分揀周期停止300毫秒後繼續。我怎麽能停下來?我查了壹下JavaScript好像沒有sleep()這樣的功能。暫停是做不到的,但妳可以想辦法達到和暫停壹樣的效果。比如在循環中做壹些無關緊要的事情。
首先,我嘗試讓while(true)總是執行空操作。執行壹段時間,然後返回排序邏輯。代碼如下所示:
for(var I = 0;我& lt3;i++) {
document . writeln(I);//DOM操作
var now =新日期()。getTime();
while(新日期()。getTime()-現在& lt3000){}
}
慢就是放慢速度。然而,它消耗了太多的資源,並且dom在排序過程中不會改變。在排序結束之前,DOM將變成排序後的樣子。但是如果您設置斷點並逐步執行它們,您可以看到排序的逐步變化。估計這個操作太耗資源了,導致瀏覽器發出了DOM操作命令,但是壹直騰不出資源來進行DOM操作。所以真正的DOM操作是在js代碼執行之後。
因此仍然沒有實現減慢JavaScript排序。
暫停JavaScript的另壹種方法:
在寫這篇文章時,我想到了另壹種停止JavaScript的方法。那就是AJAX的同步請求和超時操作。也就是說,將AJAX請求放在您想要停止的位置,同步請求,然後設置超時。超時是我們想要暫停的時間。為了避免服務器在達到超時請求之前返回我們的AJAX請求。您可以在服務器上運行類似sleep()的程序。從而確保AJAX不會返回。直接超時,然後返回我們的循環。但這只是壹個想法。有興趣的可以試試。
2.關閉和計時器。這種想法不需要減慢排序過程。相反,在排序期間使用閉包來緩存數組中的更改。然後使用setTimeout確定每個數組的狀態顯示順序。將類似下面的代碼放入排序循環中。
(函數(){
var theArr = arr . slice();//當前陣列狀態的備份
setTimeout(function(){
泡泡王國(thear);//排序的DOM操作。
},500 * time count);
time count++;//定時器序列。
})();
但是後來發現這樣寫的代碼量會比較大,修改邏輯的話會有很多地方需要修改。有許多限制,例如幾乎很難加快或減慢排序動畫的操作。所以我們必須另辟蹊徑。
3.排序中的緩存數組狀態。
也就是在排序過程中。將數組每個周期的狀態保存到數組中。然後使用該數組依次保存排序狀態。排序加壹句就行。
this . push his(arr . slice(),i-1,j,k,temp);
所以妳只需要壹個setInterval()。而且加速和減速動畫也很方便。邏輯也更容易理解。
問題2:如何加快和減慢JavaScript排序動畫。
我們第壹個問題中使用的第三種方法。獲取保存每壹步排序狀態的數組arr。然後我們可以使用setInterval()計時器來逐步顯示排序狀態。如果妳想加速或減速。對於clearInterval(),修改計時器的執行間隔,重置間隔(),並從數組中上壹個計時器執行的位置開始執行。
問題3:遞歸實現的數組怎麽樣?如果不對原始數組進行操作呢?
使用遞歸排序。它可能不會對數組進行操作,但最終會返回壹個已排序的數組。那麽我們如何在排序中獲得數組的完整狀態呢?
比如快速排序。
起初,我沒有考慮動畫,我的實現是這樣的:
函數快速排序(arr)
var len = arr.length,leftArr=【】,rightArr=【】,tag
if(len & lt;2){
返回arr
}
tag = arr【0】;
for(I = 1;我& ltleni++){
if(arr【I】& lt;=標簽){
left arr . push(arr【I】)
}否則{
right arr . push(arr【I】);
}
}
返回快速排序(leftArr)。concat(tag,quick sort(right arr));
}
然後為了考慮動畫,我重寫了它的邏輯,並使它在同壹陣列上實現。事實上,原始數組中當前子數組的起始位置是遞歸傳入的。以便對原始數組進行操作。
有兩種方法可以實現這壹點。排序邏輯略有不同。
首先是先和距離比較。如果妳遇到比妳年輕的人,把他們放在妳面前。循環序列號+1。將比自己大的放在當前排序的子數組的末尾,循環數保持不變。直到安排完成。
這種方法的缺點是即使是有序數組。它也將被重新安排。
第二種方法是在標記位之外設置壹個比較位。如果遇到比自己小的東西,把它放在前面,標記位的位置是+1,標記位和對比位之間的所有東西都向後移動壹個位置。
遇到比自己年長的人。標記位置不變,對比位置為+1。
這種方法的缺點是數組上的操作太多。優點是有序數組不會被重新排列。
模式1:
函數快速排序(arr,a,b,qArr ){
var len = arr.length,leftArr=【】,rightArr=【】,tag,I,k,len_l,len_r,lb,ra,temp
if(a = = undefined & amp;& ampb ==未定義){
a = 0;b=數組長度-1;//初始化起始位置。
}
if(qArr = = undefined ){
qArr = arr . slice();
}
if((len = = 2 & amp;& amparr【0】= = arr【1】)| | len & lt;2){
返回arr
}
tag = qArr【a】;
for(I = 1;我& ltlen) {
if(qArr【a+I】& lt;=標簽){
left arr . push(qArr【a+I】);
qArr【a+I-1】= qArr【a+I】;
qArr【a+I】= tag;
k = a+I;
i++;
}否則{
if(left arr . length+right arr . length = = len-1 ){
打破;
}
temp = qArr【a+I】;
qArr【a+I】= qArr【B- right arr . length】;
qArr【b-right arr . length】= temp;
right arr . push(temp);
k = a+I-1;
}
this . push his(qarr . slice(),a,b,k);
}
len _ l = left arr . length;
len _ r = right arr . length;
if(len _ l = = 0 ){
lb = a;
}否則{
lb = a+len _ l-1;
this . sort(left arr,a,lb,qArr);
}
if(len _ r = = 0 ){
ra = b;
}否則{
ra = b+ 1-len _ r;
this . sort(right arr,ra,b,qArr)
}
返回qArr
}
模式2:
函數快速排序2(arr,a,b,qArr ){
var len = arr.length,leftArr=【】,rightArr=【】,tag,I,j,k,temp,len_l,len_r,lb,ra;
if(a = = undefined & amp;& ampb ==未定義){
a = 0;b=數組長度-1;//初始化起始位置。
}
if(qArr = = undefined ){
qArr = arr . slice();
}
if(len & lt;2){
返回arr
}
if(len = = 2 & amp;& amparr【0】= = arr【1】){
返回arr
}
tag = qArr【a】;
for(I = 1,k = 0;我& ltlen) {
if(qArr【a+I】》;=標簽){
right arr . push(qArr【a+I】);
i++;
}否則{
temp = qArr【a+I】;
for(j = a+I;j & gta+k;j-){
qArr【j】= qArr【j-1】;
//this . push his(qarr . slice(),a,b,a+k);
}
qArr【a+k】= temp;
left arr . push(temp);
k++;
i++;
}
this . push his(qarr . slice(),a,b,a+k,I-1);
}
len _ l = left arr . length;
len _ r = right arr . length;
if(len _ l = = 0 ){
lb = a;
}否則{
lb = a+len _ l-1;
this . sort(left arr,a,lb,qArr);
}
if(len _ r = = 0 ){
ra = b;
}否則{
ra = b+ 1-len _ r;
this . sort(right arr,ra,b,qArr)
}
返回qArr
}
具體來說,下面會有動畫演示。
問題四:動畫的流暢性。
用於排序動畫的DOM操作既多又快。我在這裏做的優化只是為了使每個排序步驟只涉及壹個DOM操作。全部都是JavaScript拼接,壹次性替換。類似於以下代碼。
渲染:
主要實現了:
冒泡排序的JavaScript動畫演示
插入排序JavaScript動畫演示
選擇排序JavaScript動畫演示
快速排序JavaScript動畫演示
合並排序的JavaScript動畫演示
希爾排序JavaScript動畫演示