列表中查找数据有两种方法:顺序查找和二分查找。顺序查找使用于元素随机排列的列表;二分查找适用于元素已排序的列表。二分查找效率高,但是必须花费额外时间将列表中的元素排序
顺序查找
时间复杂度:O(n)
function seqSearch(arr,data){ for(var i=0;i<arr.length;i++){ if(arr[i] == data){ return true; } } return false; }
//返回匹配到的位置信息
function seqSearch(arr,data){ for(var i=0;i<arr.length;i++){ if(arr[i] == data){ return i; } } return -1; }
上述方法通过使用js的内置函数indexOf可以达到同样的效果,如果没有则返回-1,如果有则返回位置下标
使用自组织数据
原理:通过将频繁查找到的元素放在数组的起始位置,减少查找的次数,数据的查找遵循‘80-20’原则,即80%的操作都是对20%的数据进行查找,自组织的方法最终将这20%的数据移动到开始位置
//每查找一次就将其向前移动一个位置,如果查找次数够多,则会移动到数组的第一个为位置 function controlSearch(arr,data){ for(var i=0;i<arr.length;i++){ var temp; if(arr[i] == data){ if(i>0){ temp = arr[i-1]; arr[i-1] = arr[i]; arr[i] = temp; } return true; } } return false; }
更好的自组织数据
原理:如果元素已经很接近起始位置,则不会移动,如果在20%之外,则将其移动到第一个位置
function controlSearch(arr,data){ for(var i=0;i<arr.length;i++){ var temp; if(arr[i] == data && i > (arr.length*0.2)){ temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; return arr; }else if(arr[i] == data){ return arr; } } return false; }
二分查找
算法描述:
(1)将数组的第一个位置设置为下边界(0);
(2)将数组最后一个元素所在位置设置为上边界(数组长度减1)
(3)如下边界等于或小于上边界,则做如下操作
a. 将中点设置为(上边界加下边界)除以2
b. 如果中点的元素小于查询的值,则将下边界设置为中点元素所在下标加 1。
c. 如果中点的元素大于查询的值,则将上边界设置为中点元素所在下标减 1。
d. 否则中点元素即为要查找的数据,可以进行返回。
时间复杂度:O(logn)
function binSearch(arr,data){ var left = 0; var right = arr.length-1; var mid; while (left<=right){ mid = Math.floor((left+right)/2); if(arr[mid] < data){ left = mid+1; }else if(arr[mid] > data){ right = mid-1; }else{ return mid; } } return -1; }
计算重复次数
如果查找的元素在数组中重复出现,则找到的位置在这些位置的中间,可以根据这个特性可以计算重复值的个数
function count(arr,data){ var count =0; var i = binSearch(arr,data); if(i > -1){ count++; //向右查找,如果不相等了就退出循环 for(var j = i+1;j<arr.length;j++){ if(arr[j] == data){ count++; }else{ break; } } //向左查找,如果不相等了就退出循环 for(var j = i-1;j>0;j--){ if(arr[j] == data){ count++; }else{ break; } } } return count; }