变量a=[ 1, 2, 4, 6, 1, 100, 0, 10000, 三 ]; a.sort(函数(a,b){ 返回a-b; }); 控制台.log('a,',a); 函数binarySearch(arr,i){ var mid=数学地板(arr.length/2); console.log(arr[mid],i); 如果(arr[mid]===i){ 控制台.log('match',arr[mid],i); 返回arr[mid]; }else if(arr[mid]<i&&arr.length>1){ 控制台.log('mid-lower',arr[mid],i); 二进制搜索(arr.splice(mid,Number.MAX_VALUE),i); }否则如果(arr[mid]>i&&arr.length>1){ 控制台.log('mid higher',arr[mid],i); 二进制搜索(arr.splice(0,mid),i); }其他{ console.log('此处没有',i); 返回-1; } } var result=二进制搜索(a,100); console.log(结果);
-
1 另外,为什么arr.splice要修改“a”? – 4立方米 评论 2014年3月27日19:58 -
三 要返回递归状态,您需要 return二进制搜索(…) 在每种情况下。 – 厘米巴克利 评论 2014年3月27日20:01 -
拼接修改原始阵列,请参见 W3学校 ; 这包括通过引用传递它。 一个好的开始点是 nczonline.net/blog/2009/06/09/… – 桑尼·帕特尔 评论 2014年3月27日20:02 -
它被标记为不太可能帮助未来的访问者,因为这只是一个小错误。 – 克巴克利 评论 2014年3月27日20:20 -
2 为什么要返回与目标匹配的值? 这使得整个搜索变得多余! 您应该返回索引 – gb96标准 评论 2015年11月11日23:31
29个答案
函数binarySearch(arr,el,compare_fn){ 设m=0; 设n=arr.length-1; 而(m<=n){ 设k=(n+m)>>1; 设cmp=compare_fn(el,arr[k]); 如果(cmp>0){ m=k+1; }否则,如果(cmp<0){ n=k-1; }其他{ 返回k; } } 返回~m; }
-
2 -
2 -
三 -
2 返回值0没有歧义,它明确表示“在索引0处找到元素”。 为了表示“元素应该插入到索引0”,函数将返回-1(即 按位补码 (共0-“~x”==“-x-1”)。 – 凯南·E.K。 评论 2019年12月18日13:04 -
2
二进制搜索 (ES6)
自下而上
函数binarySearch(arr,val){ 设start=0; 设end=arr.length-1; while(开始<=结束){ 让mid=数学地板((开始+结束)/2); if(arr[mid]===val){ 返回中间; } if(val<arr[mid]){ 结束=中间-1; }其他{ 开始=中间+1; } } 返回-1; } 常数arr=[0,1,2,3,4,6100010000]; console.log(二进制搜索(arr,100));// 6
递归
函数binarySearch(arr,val,start=0,end=arr.length-1){ const mid=数学地板((开始+结束)/2); 如果(val===arr[mid]){ 返回中间; } if(开始>=结束){ 返回-1; } 返回值<arr[mid] ? 二进制搜索(arr,val,start,mid-1) :二进制搜索(arr,val,mid+1,end); } 常数arr=[0,1,2,3,4,6100010000]; console.log(二进制搜索(arr,1000));//- 1
/** *返回0<=i<=array.length,这样! pred(数组[i-1])和&pred(数组[i])。 */ 函数binarySearch(数组,pred){ 设lo=-1,hi=array.length; 而(1+lo<hi){ 常数mi=lo+((hi-lo)>>1); if(pred(数组[mi])){ hi=英里; }其他{ lo=mi; } } 返回hi; }
二进制搜索(数组,j=>0<=比较(项,j));
/** *返回i,使数组[i-1]<item<=array[i]。 */ 函数lowerBound(数组,项){ return binarySearch(数组,j=>项<=j); } /** *返回i,使数组[i-1]<=项<array[i]。 */ 函数upperBound(数组,项){ return binarySearch(数组,j=>项<j); }
-
1 虽然这并不能完全回答最初的问题(虽然我对最初的问题的意义感到困惑),但我还是投了赞成票,因为在SO上很难找到好的信息。有一个建议,如果生活允许,请为历史较长、活动较多的问题提供这样的答案。 这样做将使更多的人更容易获得您的知识和经验。:-) – 诺洛 评论 2017年3月14日8:41 -
1 -
1 -
1 -
1 @多米尼克很清楚,问题很好! (嗨+洛) 只要元素多于整数类型范围的一半,就会溢出。 这是这些类型计算中的一个众所周知的问题,请参见示例 ai.googleblog.com/2006/06/… – 乔基 评论 2020年8月10日5:15
// ... 如果(arr[mid]===i){ 控制台.log('match',arr[mid],i); 返回arr[mid]; }else if(arr[mid]<i&&arr.length>1){ 控制台.log('mid-lower',arr[mid],i); return binarySearch(arr.splice(mid,Number.MAX_VALUE),i); }else if(arr[mid]>i&&arr.length>1){ 控制台.log('mid higher',arr[mid],i); return binarySearch(arr.splice(0,mid),i); }其他{ // ...
𝗬𝗼𝘂 𝘄𝗮𝗻𝘁 𝘀𝗽𝗲𝗲𝗱? 𝗥𝗲𝗮𝗱 𝘁𝗵𝗶𝘀.
常数Arr=[0,4,5,6,9,13,14,21,27,44]; const s=sArr[Math.random()*sArr.length|0]; document.body.innerHTML=s+“is at”+压缩BS(sArr,s); 函数compactBS(数组,searchedValue,ARG_start,ARG_len){ //`void 0`是`undefined的缩写` //[start,start+len)的范围:只有start包含在内。它有效 //类似于“…”.substr(start,len).indexOf(sValue) //`void 0`是`undefined的缩写` var开始=ARG_start |0; var len=ARG_len===无效0? array.length|0:开始+(ARG_len|0)|0; var偏移=0; 对于(var i=30;i>=0;i=i-1|0){ 偏移量=开始+((1<<i)-1|0)|0; if(偏移<长度){ 开始=开始+((数组[offset]<searchedValue)<<i)|0; } } if(数组[start|0]!==searchedValue){ //删除此if-statement以返回下一个最接近的 //元素从searched-for值向下 //如果值小于 //阵列。 https://stackoverflow.com/a/44981570/5601591 return-1-开始|0; } 返回开始|0; }
如果找到该值,则返回该值的索引。 如果找不到该值,则返回 -1-最近指数 其中nearestIndex是找到的索引,它是最接近的数字<=索引,上限为0。 如果数组没有在指定范围内排序,那么它将返回一些无意义的数字。
常数Arr=[0,4,5,6,9,13,14,21,27,44]; const s=sArr[Math.random()*sArr.length|0]; document.body.innerHTML=s+“位于索引”+goodBinarySearch(sArr,s); 函数goodBinarySearch(数组、sValue、ARG_start、ARG_len){ //范围[start,start+len):只有start包含在内。它可以工作 //类似于“…”.substr(start,len).indexOf(sValue) //`void 0`是`undefined的缩写` var开始=ARG_start |0; var len=ARG_len===无效0? (array.length|0)-开始|0:ARG_len|0; var偏移=0; if((偏移=开始+0x3fffffff|0)<len){ start=start+((array[offset]<sValue)<<30)|0; } if((偏移=开始+0x1fffffff|0)<len){ start=开始+((数组[offset]<sValue)<<29)|0; } if((offset=start+0x0fffffff |0)<len){ start=开始+((数组[offset]<sValue)<<28)|0; } if((偏移=开始+0x07ffffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<27)|0; } if((偏移=开始+0x03ffffff|0)<len){ start=start+((array〔offset〕<sValue)<<26)|0; } if((偏移=开始+0x01ffffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<25)|0; } if((偏移=开始+0x00ffffff|0)<len){ start=开始+((数组[offset]<sValue)<<24)|0; } if((offset=start+0x007fffff |0)<len){ start=开始+((数组[offset]<sValue)<<23)|0; } 如果((偏移量=开始+0x003fffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<22)|0; } if((offset=start+0x001fffff |0)<len){ 开始=开始+((数组[offset]<sValue)<<21)|0; } if((offset=start+0x000fffff |0)<len){ start=开始+((数组[offset]<sValue)<<20)|0; } if((偏移=开始+0x0007ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<19)|0; } if((偏移=开始+0x0003ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<18)|0; } if((偏移=开始+0x0001ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<17)|0; } if((偏移=开始+0x0000ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<16)|0; } if((偏移=开始+0x00007fff|0)<len){ 开始=开始+((数组[offset]<sValue)<<15)|0; } if((偏移=开始+0x00003fff|0)<len){ 开始=开始+((数组[offset]<sValue)<<14)|0; } if((offset=start+0x00001fff |0)<len){ 开始=开始+((数组[offset]<sValue)<<13)|0; } if((offset=start+0x00000fff |0)<len){ 开始=开始+((数组[offset]<sValue)<<12)|0; } if((偏移量=开始+0x000007ff|0)<len){ start=start+((array〔offset〕<sValue)<<11)|0; } if((偏移量=开始+0x000003ff|0)<len){ 开始=开始+((数组[offset]<sValue)<<10)|0; } if((偏移量=开始+0x000001ff|0)<len){ 开始=开始+((数组[offset]<sValue)<<9)|0; } if((偏移=开始+0x000000ff |0)<len){ start=开始+((数组[offset]<sValue)<<8)|0; } if((偏移=开始+0x0000007f |0)<len){ start=start+((array〔offset〕<sValue)<<7)|0; } if((偏移=开始+0x0000003f |0)<len){ 开始=开始+((数组[offset]<sValue)<<6)|0; } if((偏移=开始+0x0000001f |0)<len){ 开始=开始+((数组[offset]<sValue)<<5)|0; } if((偏移量=开始+0x0000000f|0)<len){ 开始=开始+((数组[offset]<sValue)<<4)|0; } 如果((偏移量=开始+0x00000007|0)<len){ start=开始+((数组[offset]<sValue)<<3)|0; } if((偏移=开始+0x00000003|0)<len){ start=开始+((数组[offset]<sValue)<<2)|0; } if((偏移量=开始+0x00000001|0)<len){ start=开始+((数组[offset]<sValue)<<1)|0; } if(开始<len){ 开始=开始+((数组[开始]<sValue)<<0)|0; } if(数组[start|0]!==sValue){ //删除此if-statement以返回下一个最接近的 //元素从searched-for值向下 //如果值小于 //数组。 https://stackoverflow.com/a/44981570/5601591 return-1-开始|0; } 返回开始|0; }
常数Arr=[0,4,5,6,9,13,14,21,27,44]; const s=sArr[Math.random()*sArr.length|0]; document.body.innerHTML=s+“位于索引”+fastBinarySearch(sArr,s); 函数fastBinarySearch(数组、sValue、ARG_start、ARG_len){ //范围[start,start+len):只有start包含在内。它可以工作 //类似于“…”.substr(start,len).indexOf(sValue) //“void 0”是“undefined”的简写` var开始=ARG_start |0; var len=ARG_len===无效0? (array.length|0)-开始|0:ARG_len|0; var偏移=0,nCB=0; if((开始+0x00007fff |0)<len){ if((开始+0x007fffff |0)<len){ if((开始+0x07ffffff|0)<len){ 如果((起始+0x1fffff|0)<len){ if((偏移=开始+0x3fffffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<30)|0; } if((偏移=开始+0x1fffffff|0)<len){ start=开始+((数组[offset]<sValue)<<29)|0; } } if((offset=start+0x0fffffff |0)<len){ start=开始+((数组[offset]<sValue)<<28)|0; } 如果((偏移量=开始+0x07fffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<27)|0; } } if((开始+0x01ffffff|0)<len){ if((偏移=开始+0x03ffffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<26)|0; } if((偏移=开始+0x01ffffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<25)|0; } } if((偏移=开始+0x00ffffff|0)<len){ start=开始+((数组[offset]<sValue)<<24)|0; } if((offset=start+0x007fffff |0)<len){ start=开始+((数组[offset]<sValue)<<23)|0; } } if((开始+0x0007ffff|0)<len){ if((开始+0x001fffff |0)<len){ if((offset=start+0x003fffff |0)<len){ 开始=开始+((数组[offset]<sValue)<<22)|0; } if((offset=start+0x001fffff |0)<len){ 开始=开始+((数组[offset]<sValue)<<21)|0; } } if((offset=start+0x000fffff |0)<len){ start=开始+((数组[offset]<sValue)<<20)|0; } if((偏移=开始+0x0007ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<19)|0; } } if((开始+0x0001ffff|0)<len){ if((偏移=开始+0x0003ffff|0)<len){ start=start+((array〔offset〕<sValue)<<18)|0; } if((偏移=开始+0x0001ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<17)|0; } } if((偏移=开始+0x0000ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<16)|0; } if((偏移=开始+0x00007fff|0)<len){ 开始=开始+((数组[offset]<sValue)<<15)|0; } } if((开始+0x0000007f |0)<len){ 如果((起始+0x000007ff|0)<len){ if((开始+0x00001fff |0)<len){ if((偏移=开始+0x00003fff|0)<len){ 开始=开始+((数组[offset]<sValue)<<14)|0; } if((offset=start+0x00001fff |0)<len){ 开始=开始+((数组[offset]<sValue)<<13)|0; } } if((offset=start+0x00000fff |0)<len){ start=start+((array[offset]<sValue)<<12)|0; } if((偏移量=开始+0x000007ff|0)<len){ 开始=开始+((数组[offset]<sValue)<<11)|0; } } if((开始+0x000001ff|0)<len){ if((偏移量=开始+0x000003ff|0)<len){ 开始=开始+((数组[offset]<sValue)<<10)|0; } if((偏移量=开始+0x000001ff|0)<len){ 开始=开始+((数组[offset]<sValue)<<9)|0; } } if((偏移=开始+0x000000ff |0)<len){ start=开始+((数组[offset]<sValue)<<8)|0; } if((偏移=开始+0x0000007f |0)<len){ 开始=开始+((数组[offset]<sValue)<<7)|0; } } if((开始+0x00000007|0)<len){ if((开始+0x0000001f |0)<len){ if((偏移=开始+0x0000003f |0)<len){ 开始=开始+((数组[offset]<sValue)<<6)|0; } if((偏移=开始+0x0000001f |0)<len){ 开始=开始+((数组[offset]<sValue)<<5)|0; } } if((偏移量=开始+0x0000000f|0)<len){ 开始=开始+((数组[offset]<sValue)<<4)|0; } if((偏移=开始+0x00000007|0)<len){ start=开始+((数组[offset]<sValue)<<3)|0; } } 偏移量=开始+0x00000003|0; nCB=-(偏移量<len |0)|0; start=开始+(((数组[offset&nCB]<sValue)<<2)&nCB)|0; 偏移量=开始+0x00000001|0; nCB=-(偏移量<长度|0)|0; start=开始+(((数组[offset&nCB]<sValue)<<1)&nCB)|0; 偏移=开始; nCB=-(偏移量<长度|0)|0; start=开始+((数组[offset&nCB]<sValue)&nCB)|0; if(array[start|0]!==sValue){ //删除此if-statement以返回下一个最接近的 //元素从searched-for值向下 //如果值小于 //数组。 https://stackoverflow.com/a/44981570/5601591 return-1-开始|0; } 返回开始|0; }
const clz32=数学.clz32 | |(函数(log,LN2){ 返回函数(x){ 返回31-log(x>>>0)/LN2|0;// “0”的作用类似于math.floor }; })(数学日志,数学LN2); const ArrayProtoSlice=数组原型.slice; 常数Arr=[0,4,5,6,9,13,14,21,27,44]; const compFunc=最快BS(sArr); for(var i=0,str=“”,len=sArr.length|0;i<len;i=i+1|0) str+=sArr[i]+“位于”+compFunc(sArr]i)+“<br/>”; document.body.innerHTML=str;// 显示结果 函数fastestBS(数组、ARG_start、ARG_len){ //范围[start,start+len):只有start包含在内。它可以工作 //类似于“…”.substr(start,len).indexOf(sValue) //`void 0`是`undefined的缩写` var init_start=ARG_start |0; var len=ARG_len===无效0? array.length |0:init_start+(ARG_len |0)|0; 常量compGoto=clz32(长度)&31; var arrPadded=数组; var relLen=len-初始化开始|0; if(relLen&(relLen-1)){//如果不是2的幂 var sizeUp=relLen; sizeUp|=sizeUp>>>16; sizeUp |=sizeUp>>8; sizeUp|=sizeUp>>>4; sizeUp|=sizeUp>>>2; sizeUp|=sizeUp>>>1; sizeUp=sizeUp+1-relLen|0; arrPadded=ArrayProtoSlice.call(数组); var accCur=[数组[len-1|0]]; while(1<sizeUp&&accCur.length<65536){ if(sizeUp&1)arrPadded.push.apply(arrPaded,accCur); sizeUp>>>=1; accCur.推送应用(accCur,accCur); } for(var i=0;i<sizeUp;i=i+1|0){ arrPadded.push.apply(arrPaded,accCur); } } 返回函数(sValue){ var开始=init_start |0,偏移=0; 开关(compGoto){ 案例1: 开始=开始+((arrPadded[start+0x3fffffff|0]<sValue)<<30)|0; 案例2: 开始=开始+((arrPadded[start+0x1fffffff|0]<sValue)<<29)|0; 案例3: start=开始+((arrPadded[start+0x0fffffff|0]<sValue)<<28)|0; 案例4: start=开始+((arrPadded[start+0x07ffffff|0]<sValue)<<27)|0; 案例5: start=开始+((arrPadded[start+0x03ffffff|0]<sValue)<<26)|0; 案例6: start=开始+((arrPadded[start+0x01ffffff|0]<sValue)<<25)|0; 案例7: start=开始+((arrPadded[start+0x00ffffff|0]<sValue)<<24)|0; 情况8: start=开始+((arrPadded[start+0x007fffff|0]<sValue)<<23)|0; 案例9: start=start+((arrPadded[start+0x003fffff |0]<sValue)<<22)|0; 案例10: start=开始+((arrPadded[start+0x001fffff |0]<sValue)<<21)|0; 案例11: start=start+((arrPadded[start+0x000fffff |0]<sValue)<<20)|0; 案例12: start=开始+((arrPadded[start+0x0007ffff|0]<sValue)<<19)|0; 案例13: start=开始+((arrPadded[start+0x0003ffff|0]<sValue)<<18)|0; 案例14: start=开始+((arrPadded[start+0x0001ffff|0]<sValue)<<17)|0; 案例15: start=start+((arrPadded[start+0x0000fffff|0]<sValue)<<16)|0; 案例16: start=开始+((arrPadded[start+0x00007fff|0]<sValue)<<15)|0; 案例17: start=开始+((arrPadded[start+0x00003fff|0]<sValue)<<14)|0; 案例18: start=开始+((arrPadded[start+0x00001fff|0]<sValue)<<13)|0; 案例19: start=开始+((arrPadded[start+0x00000fff|0]<sValue)<<12)|0; 案例20: start=开始+((arrPadded[start+0x000007ff|0]<sValue)<<11)|0; 案例21: start=开始+((arrPadded[start+0x000003ff|0]<sValue)<<10)|0; 案例22: start=开始+((arrPadded[start+0x000001ff|0]<sValue)<<9)|0; 案例23: start=开始+((arrPadded[start+0x000000ff|0]<sValue)<<8)|0; 案例24: start=开始+((arrPadded[start+0x0000007f|0]<sValue)<<7)|0; 案例25: start=开始+((arrPadded[start+0x0000003f|0]<sValue)<<6)|0; 案例26: start=开始+((arrPadded[start+0x0000001f|0]<sValue)<<5)|0; 案例27: 开始=开始+((arrPadded[start+0x0000000f|0]<sValue)<<4)|0; 案例28: 开始=开始+((arrPadded[start+0x00000007|0]<sValue)<<3)|0; 案例29: start=开始+((arrPadded[start+0x00000003|0]<sValue)<<2)|0; 案例30: start=开始+((arrPadded[start+0x00000001|0]<sValue)<<1)|0; 案例31: start=开始+((arrPadded[start]<sValue)<<0)|0; } if(arrPadded[开始|0]!==sValue){ if(len<=start)start=len-1 |0;// 因为我们将阵列的功率增加到2的下一次方 //删除此if-statement以返回下一个最接近的 //元素从searched-for值向下 //如果该值小于 //数组。 https://stackoverflow.com/a/44981570/5601591 return-1-开始|0; } 返回启动; }; }
(函数(文档){“使用严格”; var textarea=document.getElementById(“输入框”), searchinput=文档.getElementById('search'), searchStart=文档.getElementById('start'), searchedLength=文档.getElementById('length'), resultbox=文档.getElementById('result'), 超时ID=-1; 函数doUpdate(){ 尝试{ var txt=textarea.value.replace(/\s*\[|\]\s*/g,'').split(','); var arr=JSON.parse(textarea.value); var searchval=JSON.parse(searchinput.value); var textmtchs=textarea.value.match(/\s*\[|\]\s*/g); var start=searchStart.value | | void 0; var sub=searchedLength.value | | void 0; txt=参考排序(txt,arr); textarea.value=textmtchs[0]+ txt.join(',')+ textmtchs[textmtchs.length-1]; arr=JSON.parse(textarea.value); resultbox.value=fastBinarySearch(arr,searchval,start,sub); }捕捉(e){ resultbox.value=“错误”; } } textarea.oninput=搜索输入.oninput= searchStart.oninput=搜索长度.oninpout= textarea.onkeyup=searchinput.onkeyup= searchStart.onkeyup=搜索长度.onkeyup= text区域.onchange=搜索输入.onchange= searchStart.onchange=搜索长度.onchange=函数(e){ 清除超时(超时ID); timeoutID=setTimeout(doUpdate,e.target===textarea?384:125); } 函数refSort(targetData,refData){ var索引=Object.keys(refData); indexs.sort(函数(indexA,indexB){ if(refData[indexA]<refData[indexB])返回-1; if(refData[indexA]>refData[indexB])返回1; 返回0; }); return-indexs.map(函数(i){return-targetData[i]}) } 函数fastBinarySearch(数组、sValue、ARG_start、ARG_len){ //范围[start,start+len):只有start包含在内。它可以工作 //类似于“…”.substr(start,len).indexOf(sValue) //`void 0`是`undefined的缩写` var开始=ARG_start |0; var len=ARG_len===无效0? (array.length|0)-开始|0:ARG_len|0; var偏移=0,nCB=0; if((开始+0x00007fff |0)<len){ if((开始+0x007fffff |0)<len){ if((开始+0x07ffffff|0)<len){ if((开始+0x1fffffff|0)<len){ if((偏移=开始+0x3fffffff|0)<len){ start=开始+((数组[offset]<sValue)<<30)|0; } if((偏移=开始+0x1fffffff|0)<len){ start=开始+((数组[offset]<sValue)<<29)|0; } } if((offset=start+0x0fffffff |0)<len){ start=开始+((数组[offset]<sValue)<<28)|0; } if((偏移=开始+0x07ffffff|0)<len){ start=start+((array〔offset〕<sValue)<<27)|0; } } if((开始+0x01ffffff|0)<len){ if((偏移=开始+0x03ffffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<26)|0; } if((偏移=开始+0x01ffffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<25)|0; } } if((偏移=开始+0x00ffffff|0)<len){ start=开始+((数组[offset]<sValue)<<24)|0; } 如果((偏移量=开始+0x007fffff|0)<len){ start=开始+((数组[offset]<sValue)<<23)|0; } } if((开始+0x0007ffff|0)<len){ if((开始+0x001fffff |0)<len){ if((offset=start+0x003fffff |0)<len){ 开始=开始+((数组[offset]<sValue)<<22)|0; } if((offset=start+0x001fffff |0)<len){ start=start+((array〔offset〕<sValue)<<21)|0; } } if((offset=start+0x000fffff |0)<len){ start=开始+((数组[offset]<sValue)<<20)|0; } if((偏移=开始+0x0007ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<19)|0; } } if((开始+0x0001ffff|0)<len){ if((偏移=开始+0x0003ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<18)|0; } if((偏移=开始+0x0001ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<17)|0; } } if((偏移=开始+0x0000ffff|0)<len){ 开始=开始+((数组[offset]<sValue)<<16)|0; } if((偏移=开始+0x00007fff|0)<len){ 开始=开始+((数组[offset]<sValue)<<15)|0; } } if((开始+0x0000007f |0)<len){ if((开始+0x000007ff|0)<len){ if((开始+0x00001fff |0)<len){ if((偏移=开始+0x00003fff|0)<len){ 开始=开始+((数组[offset]<sValue)<<14)|0; } if((offset=start+0x00001fff |0)<len){ 开始=开始+((数组[offset]<sValue)<<13)|0; } } if((offset=start+0x00000fff |0)<len){ 开始=开始+((数组[offset]<sValue)<<12)|0; } 如果((偏移量=开始+0x000007ff|0)<len){ 开始=开始+((数组[offset]<sValue)<<11)|0; } } if((开始+0x000001ff|0)<len){ if((偏移量=开始+0x000003ff|0)<len){ 开始=开始+((数组[offset]<sValue)<<10)|0; } if((偏移量=开始+0x000001ff|0)<len){ 开始=开始+((数组[offset]<sValue)<<9)|0; } } if((偏移=开始+0x000000ff |0)<len){ start=start+((array〔offset〕<sValue)<<8)|0; } if((偏移=开始+0x0000007f |0)<len){ 开始=开始+((数组[offset]<sValue)<<7)|0; } } if((开始+0x00000007|0)<len){ if((开始+0x0000001f |0)<len){ if((偏移=开始+0x0000003f |0)<len){ 开始=开始+((数组[offset]<sValue)<<6)|0; } 如果((偏移量=起始+0x0000001f|0)<len){ 开始=开始+((数组[offset]<sValue)<<5)|0; } } if((偏移量=开始+0x0000000f|0)<len){ 开始=开始+((数组[offset]<sValue)<<4)|0; } if((偏移=开始+0x00000007|0)<len){ start=开始+((数组[offset]<sValue)<<3)|0; } } 偏移量=开始+0x00000003|0; nCB=-(偏移量<长度|0)|0; start=开始+(((数组[offset&nCB]<sValue)<<2)&nCB)|0; 偏移量=开始+0x00000001|0; nCB=-(偏移量<长度|0)|0; start=开始+(((数组[offset&nCB]<sValue)<<1)&nCB)|0; 偏移=开始; nCB=-(偏移量<长度|0)|0; start=开始+((数组[offset&nCB]<sValue)&nCB)|0; if(数组[start|0]!==sValue){ //删除此if-statement以返回下一个最接近的 //元素从searched-for值向下 //如果值小于 //数组。 https://stackoverflow.com/a/44981570/5601591 return-1-开始|0; } 返回开始|0; } })(文件);
数组(必须是有效的JSON数组)</h3> <textarea placeholder=“[-24,-12,0,0,9,16,18,64,80]”type=“text”rows=6 style=“width:calc(100%-.5em);display:block”id=“inputbox”>[-24、-12、0、0、9、16、18、64、80]</textarea> <table style=“table-layat:fixed;font-size:1.2em”width=“100%”><tbody> <tr> 搜索值:<input type=“text”id=“Search”Value=“-12”style=“width:8em;text-align:center;float:right”/></td> <td></td> 结果索引:<input type=“text”id=“result”value=“1”style=“width:8em;text-align:center;float:right”readonly=“”/> </tr> <tr> 开始索引:<input type=“text”id=“Start”value=“”placeholder=“(0)”style=“width:8em;text-align:center;float:right”/></td> <td></td> 搜索长度:<input type=“text”id=“Length”value=“”placeholder=“(array Length)”style=“width:8em;text-align:center;float:right”/> </tr> </tbody></table>
-
2 我只想指出,我的版本被指定返回 阵列长度 对于空数组。 你可以 返回lo 如果你愿意! pred(array[i])&pred(数组[1+i]),不需要额外的(昂贵的)比较。 这个 嗨+洛 代码中的术语可能溢出,这是习惯用法所避免的 lo+((hi-lo)>>1) .我认为 如果…否则 可读性比 持续 +标签;)。 我的版本支持任意比较函子,除其他外,它只能比较部分数据。;) – 乔基 评论 2017年7月29日12:21 -
-
@Joki是的,如果你搜索 未定义 在空数组中( [] ),然后它会返回 0 而不是 -1 然而,我怀疑有很多人(如果有的话)使用 未定义 存储值。 因此,我怀疑额外检查所需的额外开销是否会被使用。 – 千斤顶G 评论 2017年8月4日20:56 -
@joki任意比较函数在javascript中速度较慢(除非是本机实现的),因为每次调用任何函数时,都必须将函数的上下文推送到堆栈上,然后在函数完成执行后从堆栈中弹出。 这种每一步都不停地推动/弹出的方式效率相当低。 – 千斤顶G 评论 2018年7月15日0:29 -
2 ……这就是为什么二进制搜索比线性搜索性能更好的原因——前者只进行对数数量的比较,而后者则会在比较成本较高的情况下产生很大差异。 在不改变渐进复杂性的情况下,固定搜索算法中的比较会使它的通用性大大降低,因此对大量数据的预期加速比要小得多。 – 乔基 评论 2018年7月15日8:27
函数bsearch(Arr,value){ var低=0,高=Arr.长度-1,中间; while(低<=高){ mid=数学地板((低+高)/2); 如果(Arr[mid]==值)返回mid; 否则,如果(Arr[mid]<值)低=mid+1; 其他高=中等1; } 返回-1; }
函数binarySearch(a,compare){ 设le=0, ri=a.length-1; while(le<=ri){ 设mid=(le+ri)>>1, cmp=比较(a[mid]); 如果(cmp>0){ le=中间+1; }否则,如果(cmp<0){ ri=中间-1; }其他{ 返回中间; } } 返回le; } 函数binaryClosest(a,compare){ 设i=二进制搜索(a,比较); 如果(i===0) 返回[0]; 如果(i===a.length) 返回a[i-1]; 设d1=-比较(a[i]), d2=比较(a[i-1]); 返回d1<d2? a[i]:a[i-1]; } // 输入=[-3,-2,-1,0,1,1,2,2,2,3,3,3] findX=x=>binaryClosest(输入,项=>x-item) 测试=(exp,arg)=>{ 设x=findX(arg) console.log(exp===x?“确定”:“失败”,arg,exp,x) }; 测试(-3,-99) 测试(+3,+99) 测试(0,+0.3) 测试(0,0) 测试(0,-0.3) 测试(-1,-1.3) 测试(+1,+1.3) 测试(2,2.2) 测试(2,2.3) 测试(2,2.5) 测试(3,2.6)
递归和非递归方式 直接发表评论
/** *二进制搜索-使用递归 *@param arr-输入数组 *@param searchElement-要搜索的元素 *@param left-左索引 *@param right-右索引 */ 函数binarySearch(arr,searchElement,left,right){ let mid=数学地板((左+(右+1))/2);// 使用floor,因为我们可能会得到浮点数 if(left<=right){//如果它不是最后一个元素,请进一步处理,否则返回-1 if(arr[mid]===searchElement){//在mid处找到元素 返回中间;// 无需进一步处理 }else if(searchElement<arr[mid]){//元素可能位于上半部分 右=中间-1;// 右边是mid-1,因为我们知道mid不是正确的元素 }else{//元素可能在后半部分 左=中间+1;// 左边是mid+1,因为我们知道mid不是正确的元素 } return this.binarySearch(arr,searchElement,left,right);// 递归的 } 返回-1;// 找不到元素 } //正在调用 console.log(二进制搜索([1,2,3,4,5],2,0,4));
/** *二进制搜索-不使用递归 *@param arr-输入数组 *@param searchElement-要搜索的元素 */ 函数binarySearch(arr,searchElement){ 设left=0, 右=arr.length-1; while(left<=right){//处理直到它是最后一个元素 let mid=数学地板((左+(右+1))/2);// 使用floor,因为我们可能会得到浮点数 if(arr[mid]===searchElement){//在mid找到元素 返回中间;// 无需进一步处理 } if(searchElement<arr[mid]){//元素可能位于上半部分 右=中间-1;// 右边是mid-1,因为我们知道mid不是正确的元素 }else{//元素可能在后半部分 左=中间+1;// 左边是mid+1,因为我们知道mid不是正确的元素 } } 返回-1;// 找不到元素 } //正在调用 console.log(二进制搜索([1,2,3,4,5],2));
//执行二进制搜索以查找数组中的位置 函数binarySearch(searchElement,searchArray){ '使用严格'; var stop=搜索数组长度; var last,p=0, 增量=0; 做{ 最后一个=p; if(searchArray[p]>searchElement){ 停止=p+1; p-=增量; }else if(searchArray[p]===searchElement){ //找到匹配项! 返回p; } delta=数学下限((stop-p)/2); p+=增量// 如果delta=0,则p不被修改,循环退出 }while(last!==p); 返回-1// 找不到任何东西 };
函数binarySearch(arr,target,idx=0){ 设full_len=arr.length; if(full_len===0){ 返回null; } 让mid=数学地板(full_len/2); if(arr[mid]===目标){ return `${target}的索引是:${idx+mid}`; }否则如果(目标>arr[mid]){ 设right=arr.slice(mid+1,full_len); idx+=(full_len-right.length); return binarySearch(右,目标,idx); }else if(目标<arr[mid]){ 设left=arr.slice(0,mid); return binarySearch(left,target,idx); } } //测试: var arr=[1,27,34,42,58,69,71,85,96,151]; console.log(二进制搜索(arr,1));//=> 0 console.log(二进制搜索(arr,27));//=> 1 console.log(二进制搜索(arr,34));//=> 2 console.log(二进制搜索(arr,42));//=> 三 console.log(二进制搜索(arr,58));//=> 4 console.log(二进制搜索(arr,69));//=> 5 console.log(二进制搜索(arr,71));//=> 6 console.log(二进制搜索(arr,85));//=> 7 console.log(二进制搜索(arr,96));//=> 8 console.log(二进制搜索(arr,151));//=> 9 arr=[10、20、30、40、50、60、70、80、90、100]; console.log(二进制搜索(arr,10));//=> 0 console.log(二进制搜索(arr,20));//=> 1 console.log(二进制搜索(arr,30));//=> 2 console.log(二进制搜索(arr,40));//=> 三 console.log(二进制搜索(arr,50));//=> 4 console.log(二进制搜索(arr,60));//=> 5 console.log(二进制搜索(arr,70));//=> 6 console.log(二进制搜索(arr,80));//=> 7 console.log(二进制搜索(arr,90));//=> 8 console.log(二进制搜索(arr,100));//=> 9 var bigArr=[]; 对于(var i=1;i<=1000000;i++){ bigArr.push(i); } console.log(二进制搜索(bigArr,5342))//=>5341 console.log(二进制搜索(bigArr,254369))//=>254368 console.log(binarySearch(bigArr,2000000))//=>null console.log(binarySearch(bigArr,-1))//=>null
函数BinarySearch(数组,值){ 设high=数组长度-1; 设low=0; if(值<array〔low〕) 返回-1; if(值>数组[高]) 返回-(高+1); while(高>=低){ var中值=(高+低)>>1; if(值===数组[mid]) 返回中间; else if(值<数组[mid]) 高=中-1; 其他的 低=中等+1; } 返回-(中间+1); } var c=['alpha','apple','beta','delta','γ','zebra']; console.log(二进制搜索(c,'delta'));// 返回3 console.log(BinarySearch(c,'beet'));// 返回-2 变量a=[1,2,3,4,6,7,8,9,10]; 变量b=[1,2,3,4,5,6,7,8,9,10]; console.log(二进制搜索(a,5));// 返回-4 console.log(二进制搜索(a,11));// 返回-9 console.log(二进制搜索(b,5));// 返回4 console.log(二进制搜索(b,0));// 返回-1
函数BinarySearch(数组,值){ 设high=数组长度-1; 设low=0; if(值<数组[低]|值>数组[高]) 返回false; 而(高>=低){ 设mid=(高+低)>>1; if(值===数组[mid]) 返回true; else if(值<数组[mid]) 高=中-1; 其他的 低=中等+1; } 返回false; }
函数binarySearch(arr,val,compFunc= (a,b)=>类型val==“数字”? a-b:a.locale比较(b),i=0,j=arr.长度){ 返回i>=j? 我 :(中间=> (cmp=> cmp<0? 二进制搜索(arr,val,compFunc,i,mid) :cmp>0? 二进制搜索(arr,val,compFunc,mid+1,j) :中间 )(compFunc(val,arr[mid])) )(i+j>>1); } /////////测试/////////////////// 功能检查(arr、val、compFunc){ var fmt=JSON.stringify; var result=二进制搜索(arr,val);// 假定为默认compFunc 控制台.log(`binarySearch(${fmt(arr)},${fmt(val)})==${fpt(result)}`); if(结果>arr.length | |结果<0 | |!arr.lendth&&result ||结果<arr.length&&compFunc(val,arr[result])>0 ||result>0&compFunc(val,arr[result-1])<0)throw“意外结果!!!” } //使用数字数据进行测试: 对于(var val=0;val<12;val++) 检查([1,2,4,6,9,9,10],val,(a,b)=>a-b); //使用空数组进行测试: 检查([],12,(a,b)=>a-b); //使用字符串数据进行测试: 检查(['abc','deaf','def','g'],'dead',(a,b)=>a.localeCompare(b));
const二进制搜索=(arr,item,[低=0,高=arr.length-1]=[])=>{ const mid=数学地板((低+高)/2) 如果(低>高)返回-1//是否超出范围? 如果(arr[mid]===项)返回mid//是否找到项? return binarySearch(arr,item[ 项目>arr[mid]? 中+1:低, 项目<arr[mid]? 中1:高 ]) }
//积极的,积极的 console.log(二进制搜索([2,6,9,14,21],9))//=>2 console.log(二进制搜索([2,6,9,14,21],21))//=>4 console.log(binarySearch([2,6,9,14,21],2))//=>0 //阴性 console.log(二进制搜索([2,6,9,14,21],0))//=>-1 console.log(二进制搜索([2,6,9,14,21],-4))//=>-1 console.log(二进制搜索([2,6,9,14,21],40)//=>-1
让A=[…数组(100).keys()].map((x)=>Math.floor(Math.random()*1000)).sort((A,b)=>A-b) const二进制搜索=(A,A,b,k)=>{ const m=数学地板((b+a)/2); 控制台.log(a,m,b,k) 如果(A[m]===k){ 返回m; } 如果(A[A]<=k&&k<=A[m]){ return binarySearch(A,A,m,k) } 如果(A[m]<k&&k<=A[b]){ 返回二进制搜索(A,m+1,b,k) } 返回-1; } console.log(`key${A[30]}`); rez=二进制搜索(A,0,100,A[30]) log(`rez是${rez},${A[30]}的索引是${A.indexOf(A[30])}`); rez=二进制搜索(A,0,100,666) console.log(`rez是${rez},${666}的索引是${A.indexOf(666)});
使用 < 而不是 <= 所以少一个比较 上面允许对 正确的 -对于zig或rust之类的语言 计算中间值而不溢出 中间 -对于zig或rust之类的语言
const-binarySearch=(key,items,compareFn)=>{ 设left=0; 让right=items.length; while(左<右){ const mid=左+数学地板((右-左)/2); const cmp=比较Fn(键,项[mid]); 如果(cmp===0)返回mid; 如果(cmp<0)right=mid; 否则左=中间+1; //当right=items.length-1,key=2,items=[3]时发生 如果(right<0)抛出新错误(“rightis<0”); } 返回-1; }; 常数比较Fn=(a,b)=>a-b; 控制台.log(binarySearch(33,新的Int16Array([1,3,4,2,33,20,10,12,34]).sort(),compareFn)); console.log(binarySearch(2,新的Int16Array([3]).sort(),compareFn));
const SearchArray=(Listarr,键)=>{ const midvalues=数学下限(Listarr.length/2) if(Key===Listarr[midvalues])返回true else if(Listarr[midvalues]<=键和midvalues>0) return SearchArray(Listarr.slice(中值,Listarr.length),键) else if(Listarr[midvalues]>=键和midvalues>0) return SearchArray(Listarr.slice(0,中值),Key) 其他的 return“未找到记录” } 常量arr=[11,24,26,37,40,43,56,75,87]; console.log(SearchArray(arr,75)) console.log(SearchArray(arr,87)) console.log(SearchArray(arr,11)) console.log(SearchArray(arr,26))
功能binSearch(针、角){ 长度=arr.length; 而(长度>1){ 中点=数学地板(长度/2); 返回(针>棱[中点-1])? binSearch(针、棱缝(中点、长度)): binSearch(针、棱缝(0,中点)); } 回针===arr[0]? arr[0]:-1; }
-
-
1 -
@求求你帮帮我。我看不出有什么了不起的品质。 在这个代码片段中,拼接的使用违背了直觉,因为它用于剪切不需要的部分,而不是在搜索数组的需要部分上进行分区。 – 千斤顶G 评论 2018年7月3日23:10 -
var binarySearch=函数(arr,val){ var half=数学地板(arr.length/2); 如果(arr.length===0){ 返回-1; } else if(arr[half]===val){ console.log(“val:”,val,“arr[half]:”,arr[half]); 返回值; } else if(val>arr[half]){ console.log(“val:”,val,“arr[half]:”,arr[half]); return binarySearch(arr.slice(half,arr.length),val); } 其他{ console.log(“val:”,val,“arr〔half〕:”,arr〔half〕); return binarySearch(arr.slice(0,half),val); } } var-arr=[1,5,20,58,76,8,19,41].sort(函数(a,b){return a-b}); console.log(“排序数组:”+arr); console.log(二进制搜索(arr,76)); console.log(二进制搜索(arr,19)); console.log(二进制搜索(arr,0));
函数binarySearch(数组、目标、最大值、最小值){ //找到数组强制最大域和最小域之间的中点 var mid=((最大值-最小值)>>1)+最小值; //警报(“中点编号”+mid); console.log(中); console.log(数组[mid],“target:”+目标); if(数组[mid]===目标){ //找到目标值 console.log('match',数组[mid],目标); //警报(“匹配”,数组[mid],目标); 返回中间; } else if(mid===0) { //已检查所有值,没有目标值,返回哨兵值 返回-1; } else if(数组[mid]>目标) { //中点的值大于目标值,将新的最大值设置为当前中点 最大值=中间值; console.log('mid-lower',array[mid],target); //警报('mid lower',数组[mid],目标); //使用新的搜索域调用binarySearch return binarySearch(数组,目标,最大值,最小值); } else if(数组[mid]<目标) { //中点处的值小于目标值,将新的最小值设置为当前中点 最小值=中间值; console.log('mid higher',array[mid],target); //警报('mid higher',数组[mid],目标); //使用新的搜索域调用binarySearch return binarySearch(数组,目标,最大值,最小值); }
函数binarySearch(arr,num,l,r){ if(arr instanceof Array){ l=NaN(l)? 0:l; r=NaN(r)? 棱长-1:r; 设mid=l+1+数学四舍五入((r-l)/2-1); 控制台.log(l,r,mid,arr[mid]); 如果(num==arr[mid]){ console.log(“已找到”); 返回中间; } if(类型arr[mid]==“未定义”|l==r){ console.log(“找不到”); 返回-1; } if(num<arr[mid]){ console.log(“向左移动”); return binarySearch(arr,num,l,r-mid); } console.log(“获取权限”); return binarySearch(arr,num,mid,r); } } console.log(二进制搜索([0,0,1,1,2,3,5,6,11],2));
函数bSearch(数组,项){ var启动=0, end=项目长度-1; var middle=数学地板((结束+开始)/2); while(数组[middle]!==项&&start<end){ if(项<数组[中间]){ end=中间1; } else if(项>数组[middle]){ 开始=中间+1; } 中间=数学地板((结束+开始)/2); } if(array[item]!==中间){ console.log('notFoundMate); 返回-1; } 其他{ console.log('FoundMate); 返回中间; } }
if(数组[mid][0]<值[0])低=mid+1; if(array[mid].val<value.val)low=mid+1;
设数组=[3,4,5,6] 设值=5// 搜索的值 设mid,low=0,high=array.length; while(低<高){ 中等=低+高>>>1;// 快速除以2并四舍五入 if(数组[mid]<值)低=mid+1; 其他高=中等; } //if(array[mid]!=值)mid=-1;// 如果您寻找插入新值的位置,则可能不需要这样做 中间;// 包含找到的值位置,如果找不到,则在找到它之前
| . | // 找到中间位置 //选项1: | . v |//如果值位于右侧,则中间为顶部 | . | // 那么就是这样 //选项2: |版本|// 如果值在左边,中间是底部 | . | // 那么就是这样 //选项2的更多循环,直到找不到为止 | . | // 下次会是这样 |. | // 下次会是这样 .//下次会是这样
arr=[1,2,3,4,5]; searchTerm=2; 函数binarySearchInJS(开始,结束) { isFound=false; if(结束>开始) { //console.log(开始+“\t”+结束) mid=(结束+开始)/2; mid=数学地板(中间) if(searchTerm==arr[mid]) { isFound=true; } 其他的 { if(searchTerm<arr[mid]) { binarySearchInJS(开始,中间); } if(searchTerm>arr[mid]) { binarySearchInJS(中间+1,结束); } } } if(找到) { return“成功”; } 其他{ return“找不到”; } }
负值表示插入点 允许搜索第一个和最后一个索引 开始索引,独占结束索引 自定义比较功能
功能默认比较(o1,o2){ 如果(o1<o2){ 返回-1; } 如果(o1>o2){ 返回1; } 返回0; } /** *@param数组带比较函数的排序数组 *@param项搜索项 *@param start(可选)开始索引 *@param-end(可选)独占结束索引 *@param compare(可选)自定义比较函数 *@param bound(可选)(-1)第一个索引; (1) 最后指标; (0)无关紧要 */ 函数binarySearch(数组、项、开始、结束、比较、绑定){ if(!compare){ compare=defaultCompare; } 让from=start==null? 0:启动; 让to=(end==null?数组长度:end)-1; 让发现=-1; while(从<=到){ 常数中间=(从+到)>>>1; const compareResult=比较(数组[middle],项); 如果(compareResult<0){ 从=中间+1; } else if(compareResult>0){ 至=中间-1; } else if(!绑定){ 回归中间; } else if(绑定<0){ //第一次出现: 发现=中间; 至=中间-1; } 其他{ //上次出现时间: 发现=中间; 从=中间+1; } } 找到返回>=0? 发现:-来自-1; }
设a=[1,2,4,6,1100,0,10000,3]; a.sort(函数(a,b){ 返回a-b; }); 函数binarySearch(arr,value){ 如果(arr.length==0)返回-1; var低=0,高=arr.长度-1,中等; while(低<=高){ mid=数学地板((低+高)/2); 如果(arr[mid]==值)返回mid; 否则,如果(arr[mid]<value)low=mid+1; 其他高=中等1; } 返回-1; } console.log(二进制搜索(a,1005))
-
1 -
-
-
它不太可能改变,因为该算法是非常基本的标准,我想我以一种非常简单、易懂和快速的方式实现了它。 这是我在javascript中遗漏的一个漏洞的主要参考点。 – 伊克拉布 评论 2017年10月5日15:30