JS-七大查找算法
- 顺序查找
- 二分查找
- 插值查找
- 斐波那契查找
- 树表查找
- 分块查找
- 哈希查找
查找定义:根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。
查找算法分类:
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>
JS-七大查找算法的更多相关文章
- [Data Structure & Algorithm] 七大查找算法
查找是在大量的信息中寻找一个特定的信息元素,在计算机应用中,查找是常用的基本运算,例如编译程序中符号表的查找.本文简单概括性的介绍了常见的七种查找算法,说是七种,其实二分查找.插值查找以及斐波那契查找 ...
- 七大查找算法(附C语言代码实现)
来自:Poll的笔记 - 博客园 链接:http://www.cnblogs.com/maybe2030/p/4715035.html 阅读目录 1.顺序查找 2.二分查找 3.插值查找 4.斐波那契 ...
- 七大查找算法(Python)
查找算法 -- 简介 查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素. 查找表(Search Table):由同一类型的数据元素构成的集合 ...
- js二分查找算法
二分查找高效的前提是数据结构是有序的.就好比猜1~100之间的数,先猜50,如果太大了就猜25,如果太小了就猜75.每一次都猜最大值和最小值的中间点. 1.随机生成100个0~100之间的随机数. v ...
- 常见查找算法之php, js,python版
常用算法 >>>1. 顺序查找, 也叫线性查找, 它从第一个记录开始, 挨个进行对比, 是最基本的查找技术 javaScript 版顺序查找算法: // 顺序查找(线性查找) 只做找 ...
- JS中算法之检索算法(查找算法)
顺序查找 查找指定值 function seqSearch(arr, data) { for (var i = 0; i < arr.length; ++i) { if (arr[i] == d ...
- javascript排序 查找算法大全
在pptv的实习结束了, 忙着找工作的事,顺便把数据结构的那本书重新复习了一遍.为了加深印象,特意把里面的常用的排序.查找算法用js写了一遍 具体的实例在我的github上,大家可以访问的: http ...
- 【摩天大楼平地起】基础篇 09 简述N种查找算法
引言 在开始之前首先可以先思考一下假如没有查找算法会是什么情况?所有数据结构都需要全部遍历一遍,每次都一遍又一遍的查,从本质而言查找算法就是为了提高效率. 经过前人一代又一代的努力,目前的查找算法大致 ...
- js 实现各种算法 APP
js 实现各种算法 APP 常见算法: 排序,搜索/查找,枚举,遍历,最短路径,二叉树 open source web app desktop app react native app flutter ...
- JS数据结构与算法-概述
JS数据结构与算法概述 数据结构: 计算机存储, 组织数据的方式, 就像锅碗瓢盆 算法: 一系列解决问题的清晰指令, 就像食谱 两者关系: 程序 = 数据结构 + 算法 邂逅数据结构与算法 什么是数据 ...
随机推荐
- 使用Django时需要注意的八个要点
1.在settings.py中使用os. path.dirname() 常用代码如下: # settings.py import os PROJECT_DIR = os.path.dirname(__ ...
- Linux查找文件之Find命令
Linux系统文件中常用属性包括以下内容:名称,大小,权限,属主,属组,修改时间,访问时间等.在庞大的Linux系统中查询文件,需要借助查找工具来实现,依此可以查询相同或指定属性的文件,本文所讲的查询 ...
- K2 BPM_【解决方案】从“制造”到“智造”,K2推动制造业转型升级_业务流程管理系统
近年来,中国制造业产出占全球总产品比例越来越大,是仅次于美国的全球第二大工业制造国,中国凭借巨大的制造业总量成为名副其实的“世界工厂”.然而个性化消费的兴起正在给制造企业各环节带来冲击.在现代市场环境 ...
- 阿里面试官总结40 个 Java 多线程问题
前言 这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题. 这些多线程的问题,有些来源于各大网站.有些来源于自己的思考.可能有些问题网上有.可能有些问题对应的答案也有.也可能有些各位 ...
- ubuntu18.04安装wine
wine是一个兼容层,可以从多平台(linux,macos,等)运行windows应用. Wine (Wine Is Not an Emulator)[即Wine不是一个模拟器]是一个在Linux和U ...
- await在forEach不起作用解决【await is a reserved word】
原文链接:https://blog.csdn.net/ssbb1995/article/details/82084800 1.await 只能在 async中使用,如: async function ...
- Android笔记(三十五) Android中AsyncTask
AsyncTask<Params,Progress,Result> 是一个抽象类,通常继承这个抽象类需要指定如下几个泛型参数: 1. Params :启动任务时出入参数的类型 2. P ...
- Linux 之 软件安装
单纯一个操作系统是没有办法满足我们的需求的,所以需要各种安装各种软件来满足我们日常工作.生活需求.一般情况下,Linux常用的安装方式有两种,以CentOS为例: 1.从源代码安装软件 将软件源代码编 ...
- linux网络编程之posix线程(一)
今天继续学习posix IPC相关的东东,消息队列和共享内存已经学习过,接下来学习线程相关的知识,下面开始: [注意]:创建失败这时会返回错误码,而通常函数创建失败都会返回-1,然后错误码会保存在er ...
- 链表(python)
链表1.为什么需要链表顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活.链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理. ...