• 顺序查找
  • 二分查找
  • 插值查找
  • 斐波那契查找
  • 树表查找
  • 分块查找
  • 哈希查找

查找定义:根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。
查找算法分类:
1)静态查找和动态查找;
注:静态或者动态都是针对查找表而言的。动态表指查找表中有删除和插入操作的表。
2)无序查找和有序查找。
无序查找:被查找数列有序无序均可;
有序查找:被查找数列必须为有序数列。
平均查找长度(Average Search Length,ASL):需和指定key进行比较的关键字的个数的期望值,称为查找算法在查找成功时的平均查找长度。
对于含有n个数据元素的查找表,查找成功的平均查找长度为:ASL = Pi*Ci的和。
Pi:查找表中第i个数据元素的概率。
Ci:找到第i个数据元素时已经比较过的次数。

顺序查找

说明:顺序查找适合于存储结构为顺序存储或链接存储的线性表。
  基本思想:顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败。
  复杂度分析: 
  查找成功时的平均查找长度为:(假设每个数据元素的概率相等) ASL = 1/n(1+2+3+…+n) = (n+1)/2 ;
  当查找不成功时,需要n+1次比较,时间复杂度为O(n);
  所以,顺序查找的时间复杂度为O(n)。

    <script>
function SequenceSearch(arr, value) {
for (let i = ; i < arr.length; i++) {
if (arr[i] == value) {
return i;
}
}
return -;
}
var arr = [,,,,,,]
console.log(SequenceSearch(arr,))
</script>

二分查找

说明:元素必须是有序的,如果是无序的则要先进行排序操作。
  基本思想:也称为是折半查找,属于有序查找算法。用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表,这样递归进行,直到查找到或查找结束发现表中没有这样的结点。
  复杂度分析:最坏情况下,关键词比较次数为log2(n+1),且期望时间复杂度为O(log2n);
注:折半查找的前提条件是需要有序表顺序存储,对于静态查找表,一次排序后不再变化,折半查找能得到不错的效率。但对于需要频繁执行插入或删除操作的数据集来说,维护有序的排序会带来不小的工作量,那就不建议使用。——《大话数据结构》

    <script>
// 递归
function binarySearch(data, dest, start, end) {
if (start > end) { // 新增否则找不到进入死循环了
return false;
}
var end = end || data.length - ;
var start = start || ;
var mid = Math.floor((start + end) / );
//var mid = parseInt(start+(end-start)/2);
//直接命中
if (data[mid] == dest) {
return mid;
} if (data[mid] > dest) { // 放左
end = mid - ;
return binarySearch(data, dest, start, end);
} else { // 放右
start = mid + ;
return binarySearch(data, dest, start, end);
}
return false;
</script>
    <script>
// 非递归 用while
//代码中的判断条件必须是while (left <= right),
//否则的话判断条件不完整,比如:array[3] = {1, 3, 5};
//待查找的键为5,此时在(low < high)条件下就会找不到,因为low和high相等时,指向元素5,但是此时条件不成立,没有进入while()中 function binarySearch2(data, dest) {
var end = data.length - ;
var start = ;
while (start <= end) {
var m = Math.floor((end + ) / );
if (data[m] == dest) {
return m;
}
if (data[m] > dest) {
end = m - ;
} else {
start = m + ;
}
}
return falsex
</script>

插值查找

基本思想:基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,差值查找也属于有序查找。
mid=low+1/2*(high-low);将查找的点改进为如下:
mid=low+(key-a[low])/(a[high]-a[low])*(high-low),
  注:对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。
  复杂度分析:查找成功或者失败的时间复杂度均为O(log2(log2n))。

    <script>
function InsertionSearch(arr, val, start, end) {
var end = end || data.length - ;
var start = start || ;
var mid = start + (val - arr[low]) / (arr[end] - arr[start]) * (end - start);
if (arr[mid] == val) {
return mid;
}
if (arr[mid] > val) {
return InsertionSearch(arr, val, start, mid - );
}
else {
return InsertionSearch(arr, val, mid + , end);
}
}
</script>

斐波那契查找

斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(从第三个数开始,后边每一个数都是前两个数的和)。斐波那契查找也属于一种有序查找算法。
斐波那契数组的实现:

    <script>
function getNum1(index) {
if (index == || index == ) {
return ;
} else {
return getNum(index - ) + getNum(index - );
}
}
function getNum2(index) {
if (index == || index == ) {
return ;
} else {
var one = ;
var two = ;
for (var i = ; i <= index; i++) {
if (i == ) {
one = ;
two = ;
}
else {
var temp = one;
one = two;
two = temp + two;
}
}
return one + two
}
}
function getNum3(index) {
var F = [];
F[] = ;
F[] = ;
for (var i = ; i < index - ; i++) {
F[i] = F[i - ] + F[i - ];
}
return F[index];
}
</script>

基本思路:

相对于折半查找,一般将待比较的key值与第mid=(low+high)/2位置的元素比较,比较结果分三种情况:
1)相等,mid位置的元素即为所求
2)>,low=mid+1;
3)<,high=mid-1。
斐波那契查找与折半查找很相似,他是根据斐波那契序列的特点对有序表进行分割的。他要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1;
开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1),比较结果也分为三种
1)相等,mid位置的元素即为所求
2)>,low=mid+1,k-=2;
说明:low=mid+1说明待查找的元素在[mid+1,high]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,所以可以递归的应用斐波那契查找。
3)<,high=mid-1,k-=1。
说明:low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为F(k-1)-1个,所以可以递归 的应用斐波那契查找。

    <script>
function search(array, value) {
let low = , high = array.length - , n = array.length - ;
let mid, k = ;
//构建一个长度大于array数组的斐波那契数组
var F = [];
F[] = ;
F[] = ;
for (var i = ; i < high + ; i++) {
F[i] = F[i - ] + F[i - ];
}
while (high > F[k] - ) { //寻找第k项
k++;
}
for (let i = high; i < F[k] - ; i++) { //补全有序数组
array[i] = array[high];
}
while (low <= high) {
mid = low + F[k - ] - ;
if (array[mid] > value) {
high = mid - ;
k = k - ; //长度缩减为F[k-1]-1
} else if (array[mid] < value) {
low = mid + ;
k = k - ; //长度缩减为F[k-2]-1
} else {
if (m <= n) //相等则找到位置
return mid;
else {
return n; //大于原始长度,则说明等于数组最后一项
}
}
return -;
}
}
</script>

树表查找

最简单的树表查找算法——二叉树查找算法。
基本思想:二叉查找树是先对待查找的数据进行生成树,确保树的左分支的值小于右分支的值,然后在就行和每个节点的父节点比较大小,查找最适合的范围。 这个算法的查找效率很高,但是如果使用这种查找方法要首先创建树。
    二叉查找树(BinarySearch Tree,也叫二叉搜索树,或称二叉排序树Binary Sort Tree)或者是一棵空树,或者是具有下列性质的二叉树:
    1)若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    2)若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    3)任意节点的左、右子树也分别为二叉查找树。
    二叉查找树性质:对二叉查找树进行中序遍历,即可得到有序的数列。

索引查找(分块查找)

分块查找又称索引顺序查找,它是顺序查找的一种改进方法。
  算法思想:将n个数据元素"按块有序"划分为m块(m ≤ n)。每一块中的结点不必有序,但块与块之间必须"按块有序";即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素又都必须小于第3块中的任一元素,……
  算法流程:
  step1 先选取各块中的最大关键字构成一个索引表;
  step2 查找分两个部分:先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;然后,在已确定的块中用顺序法进行查找。

哈希查找  

哈希查找和哈希算法看这里
  哈希查找 https://www.cnblogs.com/yw09041432/p/5908444.html
  哈希算法 https://www.cnblogs.com/xiohao/p/4389672.html http://www.sohu.com/a/232586831_100078137

贪心算法

遵循一种近似解决问题的技术,期盼通过每个阶段的局部最优选择(当前最好的解),从而达到全局的最优(全局最优解)。贪心得到结果是一个可以接受的解,不一定总是得到最优的解。
最少硬币找零问题:最少硬币找零是给出要找零的钱数,以及可以用硬币的额度数量,找出有多少种找零方法。
如:美国面额硬币有:1,5,10,25
我们给36美分的零钱,看能得怎样的结果?

    <script>
function MinCoinChange(coins) {
var coins = coins;
var cache = {};
this.makeChange = function (amount) {
var change = [], total = ;
for (var i = coins.length; i >= ; i--) {
var coin = coins[i];
while (total + coin <= amount) {
change.push(coin);
total += coin;
}
}
return change;
}
}
var minCoinChange = new MinCoinChange([, , , ]);
minCoinChange.makeChange();
//一个25, 一个10, 一个1
</script>

最新文章

  1. HDU1671——前缀树的一点感触
  2. MAC下反編譯安卓APK
  3. 百度地图API示例之文本标注
  4. 关于Liferay所有的能够进行自定义和扩展的东西的总结
  5. window-messager(消息框)
  6. IOS开发之上传APP
  7. ld: symbol dyld_stub_binding_helper not found, normally in crt1.o/dylib1.o/bundle1.o for architecture i386
  8. SqlServer和Oracle中一些常用的sql语句6 存储过程
  9. Spring Boot 定时任务的使用
  10. P1052 过河 线性dp
  11. html5-常用的通用元素
  12. 阿里云视频直播API签名机制源码
  13. layui table 行号
  14. SharePoint2016配置工作流开发环境
  15. Android App组件之Fragment说明和示例
  16. mysql的水平拆分和垂直拆分 (转)
  17. django中两张表有外键关系的相互查找方法,自定义json编码方法
  18. 读Understanding the Linux Kernel, 3rd Edition有感
  19. linux 冒号用法
  20. window.open之postMessage传参数

热门文章

  1. js展开循环
  2. JMeter测试HBase
  3. 解决mysql登录警告问题
  4. IPC——概述
  5. 基于Java+Selenium的WebUI自动化测试框架(六)---浏览器初始化
  6. machine learning(11) -- classification: advanced optimization 去求cost function最小值的方法
  7. flask 杂记3
  8. 2018 南京网络预赛Sum ——莫比乌斯反演
  9. LightOJ-1020-A Childhood Game(博弈)
  10. Codeforces Round #597 (Div. 2) A. Good ol&#39; Numbers Coloring