js实现二分法查找方法

JavaScript029

js实现二分法查找方法,第1张

所谓二分法查找法,也就是折半查找,它是一种在有序数组查找特定元素的搜索算法。

参考《前端程序员面试秘籍》

思想:从数组中开始查找,如果该元素是要搜索的目标元素,则循环结束,如果不是继续下一步,如果目标元素大于或者小于中间元素,则在数组大于或者小于中间元素的那一半区域进行查找,进而重复上面操作。如果数组是空的,则找不到该目标元素。

findIndex它会返回数组中满足提供的函数的第一个元素的索引,否则返回 -1

跟findIndex差不多,只不过是倒序查找

观察可以知道findIndex 和findLastIndex的实现原理基本相同,区别只在于查找顺讯,那么如何通过实现一个函数,通过不同的传参来判断是使用findIndex还是findLastIndex呢?

实现:

新的需求:如何在一个排好序的数组中找到 value 对应的位置,保证插入数组后,依然保持有序的状态?

比如: sortedIndex([10, 20, 30], 25) // 2

如果是有序数组,那我们就不采用遍历的形式,采用二分法

看上去不错,基本实现了我们的要求,但还不够好,如果我想实现下面这种情况要怎么处理?

进阶实现:

现在尝试手写一个indexOf/lastIndexOf

indexOf和lastIndexOf都支持第二个参数fromIndex表示开始查找的位置。

在MDN上对fromIndex的解释如下:

fromIndex

开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找,-2表示从倒数第二个元素开始查找 ,以此类推。 注意:如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0.

比如:

fromIndex

从此位置开始逆向查找。默认为数组的长度减 1(arr.length - 1),即整个数组都被查找。如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。

根据以上规则,我们实现第二版

主要围绕下面两点进行

根据以上要求,看下最终实现方法

在Web开发中,JavaScript很重要,算法也很重要。下面整理了一下一些常见的算法在JavaScript下的实现,包括二分法、求字符串长度、数组去重、插入排序、选择排序、希尔排序、快速排序、冒泡法等等。仅仅是为了练手,不保证高效与美观,或许还有Bug,有时间再完善吧。

1.二分法:

function binary(items,value){

var startIndex=0,

stopIndex=items.length-1,

midlleIndex=(startIndex+stopIndex)>>>1

while(items[middleIndex]!=value &&startIndex

if(items[middleIndex]>value){

stopIndex=middleIndex-1

}else{

startIndex=middleIndex+1

}

middleIndex=(startIndex+stopIndex)>>>1

}

return items[middleIndex]!=value ? false:true

}

2.十六进制颜色值的随机生成:

function randomColor(){

var arrHex=["0","2","3","4","5","6","7","8","9","a","b","c","d"],

strHex="#",

index

for(var i=0i <6i++){

index=Math.round(Math.random()*15)

strHex+=arrHex[index]

}

return strHex

}

一个求字符串长度的方法:

function GetBytes(str){

var len=str.length,

bytes=len

for(var i=0i <leni++){

if(str.CharCodeAt>255){

bytes++

}

}

return bytes

}

3.js实现数组去重:

Array.protype.delRepeat=function(){

var newArray=new Array()

var len=this.length

for(var i=0i <leni++){

for(var j=i+1j <lenj++)

{

if(this[i]==this[j])

{

++i

}

}

newArray.push(this[i])

}

return newArray

}

4.插入排序。所谓的插入排序,就是将序列中的第一个元素看成一个有序的子序列,然后不段向后比较交换比较交换。

function insertSort(arr){

var key

for(var j = 1j <arr.length j++){

//排好序的

var i = j - 1

key = arr[j]

while(i >= 0 &&arr[i] >key){

arr[i + 1] = arr[i]

i --

}

arr[i + 1] = key

}

return arr

}

5.选择排序。其实基本的思想就是从待排序的数组中选择最小或者最大的,放在起始位置,然后从剩下的数组中选择最小或者最大的排在这公司数的后面。

function selectionSort(data)

{

var i, j, min, temp , count=data.length

for(i = 0i <count - 1i++) {

/* find the minimum */

min = i

for (j = i+1j <countj++)

{

if (data[j] <data[min])

{ min = j}

}

/* swap data[i] and data[min] */

temp = data[i]

data[i] = data[min]

data[min] = temp

}

return data

}

6.希尔排序,也称递减增量排序算法。其实说到底也是插入排序的变种。

function shellSort(array){

var stepArr = [1750, 701, 301, 132, 57, 23, 10, 4, 1]//

reverse()在维基上看到这个最优的步长较小数组

var i = 0

var stepArrLength = stepArr.length

var len = array.length

var len2 = parseInt(len/2)

for(i <stepArrLengthi++){

if(stepArr[i] >len2){

continue

}

stepSort(stepArr[i])

}

// 排序一个步长

function stepSort(step){

//console.log(step) 使用的步长统计

var i = 0, j = 0, f, tem, key

var stepLen = len%step >0 ? parseInt(len/step) + 1 : len/step

for(i <stepi++){// 依次循环列

for(j=1/*j <stepLen &&*/step * j + i <len

j++){//依次循环每列的每行

tem = f = step * j + i

key = array[f]

while((tem-=step) >= 0){// 依次向上查找

if(array[tem] >key){

array[tem+step] = array[tem]

}else{

break

}

}

array[tem + step ] = key

}

}

}

return array

}

7.快速排序。其实说到底快速排序算法就系对冒泡排序的一种改进,采用的就是算法理论中的分治递归的思想,说得明白点,它的做法就是:通过一趟排序将待排序的纪录分割成两部分,其中一部分的纪录值比另外一部分的纪录值要小,就可以继续分别对这两部分纪录进行排序不段的递归实施上面两个操作,从而实现纪录值的排序。

function quickSort(arr,l,r){

if(l <r){

var mid=arr[parseInt((l+r)/2)],i=l-1,j=r+1

while(true){

while(arr[++i] <mid)

while(arr[--j]>mid)

if(i>=j)break

var temp=arr[i]

arr[i]=arr[j]

arr[j]=temp

}

quickSort(arr,l,i-1)

quickSort(arr,j+1,r)

}

return arr

}

8.冒泡法:

function bullSort(array){

var temp

for(var i=0i <array.lengthi++)

{

for(var j=array.length-1j >ij--){

if(array[j] <array[j-1])

{

temp = array[j]

array[j]=array[j-1]

array[j-1]=temp

}

}

}

return array

}