JavaScript中的二分法插入算法
算法主体部分
var OnlineUser = { //list : 待查找的数组 //key : 待插入的值 //order : 数组的顺序 1:从小到大 0:从大到小 //start : 开始查找的起始下标位置 //end : 开始查找的结束下标位置 //例: //var arr1 = [17,15,15,14,14,13,13,8,8,7,7,6,5,4,3]; //var key = 8; //var index = OnlineUser.GetPosIndex(arr1, key,0, arr1.length, 0); GetPosIndex:function(list,key,order,start,end) { var index = -1; var halfIndex = Math.abs(parseInt((end+start)/2)); if(list[halfIndex] == key) //在中位 { index = halfIndex; } else if(list[halfIndex] < key && key < list[start])//在左半 { index = OnlineUser.GetPosIndex(list, key, order, start, halfIndex); } else if(list[end] < key && key < list[halfIndex])//在右半 { halfIndex ++ ; index = OnlineUser.GetPosIndex(list, key, order, halfIndex, end); } else if(list[start] <= key && list[halfIndex] < key) //在左边 { index = start; } else if(list[end] >= key && list[halfIndex] > key) //在右边 { index = end + 1; } else //一个值都没有 { index = 0; } return index; }, Sort:function(array){ return array.sort(function(a, b){ return b - a; }); }, GetInsIndex:function(list,key) { var index = 0; //list = this.Sort(list); for(var k=0;k<list.length;k++) { if(list[k] <= key) { index = k; break; } else if(list[k] > key) index = k+1; else if(list[k] < key) break; } return index; } }
完整的程序和测试页面
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <div id ="result"></div> </body> <script lang="javascript"> var OnlineUser = { //list : 待查找的数组 //key : 待插入的值 //order : 数组的顺序 1:从小到大 0:从大到小 //start : 开始查找的起始下标位置 //end : 开始查找的结束下标位置 //例: //var arr1 = [17,15,15,14,14,13,13,8,8,7,7,6,5,4,3]; //var key = 8; //var index = OnlineUser.GetPosIndex(arr1, key,0, arr1.length, 0); GetPosIndex:function(list,key,order,start,end) { var index = -1; var halfIndex = Math.abs(parseInt((end+start)/2)); if(list[halfIndex] == key) //在中位 { index = halfIndex; } else if(list[halfIndex] < key && key < list[start])//在左半 { index = OnlineUser.GetPosIndex(list, key, order, start, halfIndex); } else if(list[end] < key && key < list[halfIndex])//在右半 { halfIndex ++ ; index = OnlineUser.GetPosIndex(list, key, order, halfIndex, end); } else if(list[start] <= key && list[halfIndex] < key) //在左边 { index = start; } else if(list[end] >= key && list[halfIndex] > key) //在右边 { index = end + 1; } else //一个值都没有 { index = 0; } return index; }, Sort:function(array){ return array.sort(function(a, b){ return b - a; }); }, GetInsIndex:function(list,key) { var index = 0; //list = this.Sort(list); for(var k=0;k<list.length;k++) { if(list[k] <= key) { index = k; break; } else if(list[k] > key) index = k+1; else if(list[k] < key) break; } return index; } } var result = document.getElementById("result"); //测试用例,子数组第一个为从小到大顺序,第二个从大到小的顺序 var testArray = [ [[],[]], [[1],[1]], [[1,2,3,4,5],[17,15,14,13]], [[11,12,13,14,15],[7,6,5,4,3,2,1]], [[1,2,3,4,5,7,7,7,8,8,9,9,10],[17,15,15,14,14,13,13,8,8,7,7,6,5,4,3]], [[1000003,1000003,1000003,1000003,1000003,11000269],[11000269,1000003,1000003,1000003,1000003,1000003]] ]; //期望值 var expectArray = [ [[0],[0]], [[1],[0]], [[5],[4]], [[0],[0]], [[10],[7]], [[5],[1]] ]; //各用例要查找的值 var testKey = [ [8], [8], [8], [8], [8], [1000003] ]; var start =0;//开始查找的起始下标位置 var end =0; //开始查找的结束下标位置 var index = 0; //待插入的位置 for(var i=0;i<testArray.length;i++) //组数 { result.innerHTML += "<hr />"; for(var j=0;j<testArray[i].length;j++) //组单元 { if(j==1) //大到小 { start = 0; end = testArray[i][j].length - 1; index = OnlineUser.GetPosIndex(testArray[i][j], testKey[i][0],1, start, end); result.innerHTML += "<br />small -> big: ["+testArray[i][j].toString()+"], key:"+testKey[i]+", index:" + index +", expect:"+expectArray[i][j]+ ((index == expectArray[i][j])?"":",<font color='red'>NotEq</font>"); } else //从小到大 { continue; start = testArray[i][j].length - 1; end = 0; index = OnlineUser.GetPosIndex(testArray[i][j], testKey[i][0],0, start, end); result.innerHTML += "<br />big <- small: ["+testArray[i][j].toString()+"], key:"+testKey[i]+", index:" + index+", expect:"+expectArray[i][j]+ ((index == expectArray[i][j])?"":",<font color='red'>NotEq</font>"); } } } /* */ //构造测试数据 var bufferArray = []; var newArray = [10002107,10002107,10000003,10002057,10000037,10000037,10000007,10000007,10000007,10000007,10000007,10000007,10000007,10000007,10002067,10000005,10000005,10000005,10000007,10000007,10000005,10000005,10000005,10000005,10000005,10000005,10000005,10000005,10000005,10000005,10000005,10000005]; newArray.reverse(); for(var n = 0;n<10000;n++) { newArray[n] = parseInt(10000000 + Math.random() * 1000000); } var key = parseInt(10000000 + Math.random() * 1000000); //IE弹出"是否停止运行此脚本"脚本超时时间设置 //1. 打开注册表HKEY_CURRENT_USER\Software\Microsoft\InternetExplorer\Styles,如果 Styles 键不存在,创建调用 Styles 的一个新的项 //2. 创建新的 DWORD 值在此项下称为"MaxScriptStatements"并将值设置为所需的脚本语句数,如100000000 // ***************** 以下数据准确性测试 ********************* //系统法排序 var bArray = OnlineUser.Sort(newArray); //二分法插入 for(var m=0; m < newArray.length;m++) { var index = OnlineUser.GetPosIndex(bufferArray, newArray[m], 1,0, bufferArray.length-1); //var index = OnlineUser.GetPosIndex(bufferArray, newArray[m], 0, bufferArray.length,0); bufferArray.splice(index, 0, newArray[m]); } //结果打印 var a = bufferArray.toString(); var b = bArray .toString(); result.innerHTML += "<br />Rnd:" + newArray.toString(); result.innerHTML += "<br />Dic:" + a; result.innerHTML += "<br />Sys:" + b; result.innerHTML += "<br /> Eq:" + (a == b); // ***************** 以下性能测试 ********************* //将数据分为5段,做采样 var keyArr = []; for(var ki=0;ki<5;ki++) { keyArr.push(newArray.length * ki * 0.2); } var cnt = 1000; var idx =0 ; var dateStart,dateEnd,timeSpan; //遍历方法插入 result.innerHTML += "<br />"+keyArr.toString(); result.innerHTML += "<br />GetInsIndex: ckey key idx cnt t(ms)"; for(var ckey=0;ckey<keyArr.length;ckey++) { dateStart = new Date(); //@@@TEST for(var x=0;x<cnt;x++ ) { idx = OnlineUser.GetInsIndex(bArray, bArray[keyArr[ckey]]+1); } dateEnd = new Date();t = dateEnd.getTime() - dateStart.getTime(); result.innerHTML +="<br />"+ckey+" "+keyArr[ckey] + " "+idx+" "+cnt+" "+t; } cnt = 10000; //二分法插入 result.innerHTML += "<br />GetPosIndex: ckey key idx cnt t(ms)"; for(var ckey=0;ckey<keyArr.length;ckey++) { dateStart = new Date(); //@@@TEST for(var x=0;x<cnt;x++ ) { idx = OnlineUser.GetPosIndex(bArray, bArray[keyArr[ckey]]+1,1,0,bArray.length -1 ); } dateEnd = new Date();t = dateEnd.getTime() - dateStart.getTime(); result.innerHTML +="<br />"+ckey+" "+keyArr[ckey] + " "+idx+" "+cnt+" "+t; } </script> </html>
专注于机器学习、前端相关邻域。关注 全栈深入 公众号查看更多硬核文章。