【21天学习挑战赛】算法——查找算法

活动地址:CSDN21天学习挑战赛

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰

前言:
算法在程序工作中的重要意义就不再赘述了,想必您已经非常清楚了,话不多说,直接开干。
查找和排序是工作中的基本问题,在很多需求中都存在,因此就来聊聊查找算法和排序算法。由于篇幅限制此篇就先聊聊查找算法。

查找算法顾名思义,就是找到自己需要的东西。那么,从什么中找呢,可以是一堆数字,例如:[90,34,123543,6543,3235,423];也可以是一堆对象,例如:[{name:“mike”},{name:“bob”}],也可以是字符串,例如:[“hello”,“world”]。那么,又该怎么找呢,接下来就说一说,查找算法的具体方法。

顺序查找

顺序查找思路

顾名思义,顺序查找就是按照顺序查找,这个顺序是指数据在数组中的自然顺序,不是数据本身具有意义的顺序。就是从第一个开始查找直到找到或者直到最后一个。如果找到了就不必再继续找了返回什么由自己决定。

顺序查找过程

在这里插入图片描述
第一次:从第一个数据开始比对,与目标值不一致
第二次:与第二个数据比对,与目标值不一致
第三次:与第三个数据比对,与目标值不一致
第四次:与第四个数据比对,与目标值不一致
第五次:与第五个数据比对,与目标值一致,退出查找

代码

纸上得来终觉浅,觉知此事要躬行。接下来就用一个例题,具体感受一下。
需求:在一个有n个数字元素的数组nums中查找数字m,如果找到了返回其下标否则返回-1。

function search(nums, m){
	for(let i = 0, len = nums.length; i < len; i++){
		if(nums[i] === m){
			return i;
		}
	}
	return -1;
}

这道题比较简单,就是从第一个元素开始,每个元素都和m代表的值进行比对,如果值相等就是返回其下标,否则等循环结束说明没有找到就返回-1。不过在工作中只知道顺序查找还是不够,主要是因为在遇到数据较多的情况下,顺序查找就很慢,需要半天才找到,严重影响性能,如果没有交互动画提示时,甚至还会以为是bug。因此还需要学习其他查找方法。

二分查找

二分查找思路

二分查找,有时也叫折半查找。顾名思义,就是把一堆数据以中间的那个数为中心从中间分开,如果要查找的数比中间那个数大,就在中间数的右半边中查找,如果比要查找的数小就在左半边中找。右半边/左半边也和上一步一样,以中间数为中心分开,再次与要找的数比较,一直这样找下去或者直到数组的头和尾重合。

二分查找过程

在这里插入图片描述

第一次:middle=2,指向值为3的数据,与target不等
第二次:middle=1,执行值为2的数据,与target相等,结束查找

示例

好了,光说不练假把式,先弄个题练练先。
需求:在一个有n个数字元素的数组nums中查找元素m,如果找到返回其下标否则返回-1。

function binSearch(nums,m){
  let end = nums.length - 1;
  let start = 0;
  while(start <= end){
    let mid = Math.floor((end + start) / 2);
    if(arr[mid] < m){
      start = mid + 1;
    } else if(arr[mid] > m){
      end = mid - 1;
    } else {
      return mid;
    }
  }
  return -1;
}

二分查找需要找一个中间数,怎么找呢,一般就是取数组中的中间下标所指的元素。一般是把数组的长度除以2,取商的整数,这是为了避免除不尽导致存在小数不好判断的情况。毕竟javascript语言的商有小数。把中间数取好之后就开始比较,就和刚才说的一样,比中位数大向尾部找,小了向头部找,直到找到或者没找到,以上就是二分查找法。

二分排序比顺序查找法要快,毕竟一半一半的找比从头找到尾要快。
不过需要数组是有序的即排好序的,不管是从小到大(升序)还是从大到小(降序)都可以

如果是从大到小,只需要将

 if(arr[mid] < m){
      start = mid + 1;
    } else if(arr[mid] > m){
      end = mid - 1;
    } else {
      return mid;
    }

换成

 if(arr[mid] < m){
  		end = mid - 1;
    } else if(arr[mid] > m){
     start = mid - 1;
    } else {
      return mid;
    }

即可。

查找最小值和最大值

将数组的第一个元素赋值给一个变量,作为最小值,将其与下一个元素相比,如果比变量值小将该值赋值给变量。

function getMin(arr){
    let min = arr[0];
    for(let i = 0; i < arr.length; i++){
        if(arr[i] < min){
            min = arr[i];
        }
    }
    return min;
}
function getMax(arr){
    let max = arr[0];
    for(let i = 0; i < arr.length; i++){
        if(arr[i] > max){
            max = arr[i]
        }
    }
    return max;
}
自组织数据

数据在程序运行过程中自动组织。“80-20原则”:对一个数据集的80%查找操作都是对其20%的数据进行的操作。
将查找的元素向前移动一个位置,当数据被查询的足够频繁被查找的数据最终会移动到数组首部。

function search(arr, data){
    for(let i = 0; i < arr.length; i++){
        if(arr[i] === data){
            if(i > 0){
                let temp = arr[i - 1];
                arr[i - 1] = arr[i];
                arr[i] = temp;
            }
            return true;
        }
    }
    return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端御书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值