查找算法
- 直接查找(遍历的方式查找,效率较低)
- 折半查找(有顺序,类似猜数字大小,确定一个区间)
- 插值查找(与折半查找类型差不多,确定区间范围时的计算方式不同)
- 斐波拉契查找(与折半查找类型差不多,确定区间范围时的计算方式采用黄金分割比例)
- 索引查找(分块索引,倒排索引–文章关键字索引)
- 二叉排序树(二叉查找树)
- 平衡二叉树(通过树的旋转构造一棵平衡二叉树,与哈夫曼树类似)
- 多路查找树(应用,降低磁盘IO)
- 散列函数(简单查找+分布均匀)
以上是一些查找算法, 这里以折半查找与散列函数查找为例,至于为什么以这两种为例,当然是因为这两种比较简单了。
折半查找:
/**
* 折半查找
*/
public static void halfSearch(int target, int start, int end) {
if (start == end || start + 1 == end) {
System.out.println("目标不存在");
return;
}
int mid = (start + end) / 2;
if (arr[mid] == target) {
System.out.println("找到目标,下标:" + mid);
} else if (arr[mid] < target) {
halfSearch(target, mid, end);
} else if (arr[mid] > target) {
halfSearch(target, start, mid);
}
}
散列函数
散列函数的几种方法
- 直接定址法
- 数字分析法(电话号码+身份证)
- 平方取中法(先平方,取中间几位数据)
- 折叠法(分割相等的几等分,叠加求和)
- 除留余数法(取余数)
- 随机数法:关键字长度不等,采用此方法
通过以下情况分析采用不同的散列函数
计算散列地址的长度
关键字长度
散列表大小
关键字分布情况
查找频率
散列函数的核心在解决hash冲突上面,解决hash冲突有如下几种方法
分离链表法
将冲突的数据放入同一个链表中,解决冲突。
开放地址法
如果改地址已经被占用,通过一定的计算规则计算下一个地址,直到找到空位置,放入数据。
- 线性探测法(线性探测,比如直接在当前地址往后挪一位)
- 二次探测法(生成的后继散列地址不是连续的,而是跳跃式的,以便为后续数据元素留下空间从而减少聚集。)
- 随机探测法(通过随机数探测地址)
- 双散列探测法(利用第二个散列函数作为常数,每次跳过常数项,做线性探查。)
通过hash算法放入到数组中
public static void hashPush(int a, int[] arr) {
// 求余法
int mod = a % 15;
// 解决哈希冲突
while (arr[mod] != 0) {
mod = mod + 1;
}
arr[mod] = a;
}
查找
public static int hashSearch(int a) {
int mod = a % 15;
// 具有hash冲突的查找
while (arr[mod] != a && arr[mod] != 0) {
mod = mod + 1;
if (mod >= arr.length) {
return -1;
}
}
return mod;
}
下一篇文章会是关于工作流相关的文章,这个领域也是之前没有接触过的,这次在工作上用到了,正好记录一下,数据结构与算法后面就只有几大排序算法了。这样也算暂时告一段落了。
附上代码库地址:
https://gitee.com/zhoujie1/data-structure-and-algorithm.git