# 基础 查找
- 顺序查找
- 二分查找
- 插值查找
- 斐波那契查找
// ArrayList.sort.js
const ArrayList = require("./ArrayList.js");
module.exports = ArrayList;
ArrayList.prototype.sort = function (callback) {
this.arr.sort(callback);
};
# 顺序查找
从数组的第一个元素开始,逐个比较直到找到目标元素或遍历完整个数组。
ArrayList.prototype.sequentialSearch = function (item) {
const arr = this.arr;
for (let i = 0; i < arr.length; i++) {
if (item == arr[i]) {
return i;
}
}
return -1;
};
# 二分查找 (重点)
每次将数组分成两半,并在中间元素与目标值进行比较。时间复杂度为 (O(\log n))。
// 二分查找 需要有序列表
ArrayList.prototype.binarySearch = function (target) {
this.sort((a, b) => a - b);
const arr = this.arr;
let left = 0;
let right = arr.length - 1;
while (left <= right) {
let mid = left + Math.floor((right - left) / 2);
if (arr[mid] == target) {
return mid; // 找到了返回
} else if (arr[mid] < target) {
left = mid + 1; // 收缩
} else if (arr[mid] > target) {
right = mid - 1; // 收缩
}
}
// left > right 没找到
return -1;
};
# 插值查找
假设数据是均匀分布的,通过计算目标值在数组中的估计位置来减少搜索范围。平均情况下时间复杂度为 (O(\log \log n))
function interpolationSearch(arr, target) {
let low = 0;
let high = arr.length - 1;
while (low <= high && target >= arr[low] && target <= arr[high]) {
if (low === high) {
if (arr[low] === target) return low;
return -1;
}
// 计算中间位置
let pos = Math.floor(low + ((target - arr[low]) * (high - low)) / (arr[high] - arr[low]));
if (arr[pos] === target) {
return pos; // 找到目标值,返回索引
} else if (arr[pos] < target) {
low = pos + 1; // 在右半部分继续查找
} else {
high = pos - 1; // 在左半部分继续查找
}
}
return -1; // 没有找到目标值
}
# 斐波那契查找
利用斐波那契数列来分割数组,并在每次比较后减少搜索范围。斐波那契查找适用于有序数组,并且在某些情况下比二分查找更高效。
function fibonacciSearch(arr, target) {
let fib2 = 0; // (m-2)'th Fibonacci number
let fib1 = 1; // (m-1)'th Fibonacci number
let fibM = fib2 + fib1; // m'th Fibonacci number
// 扩展数组到长度为 fibM
while (fibM < arr.length) {
fib2 = fib1;
fib1 = fibM;
fibM = fib2 + fib1;
}
let offset = -1;
// 在数组中进行查找
while (fibM > 1) {
let i = Math.min(offset + fib2, arr.length - 1);
if (arr[i] < target) {
fibM = fib1;
fib1 = fib2;
fib2 = fibM - fib1;
offset = i;
} else if (arr[i] > target) {
fibM = fib2;
fib1 = fib1 - fib2;
fib2 = fibM - fib1;
} else {
return i; // 找到目标值,返回索引
}
}
// 检查最后一个元素是否是目标值
if (fib1 && arr[offset + 1] === target) {
return offset + 1;
}
return -1; // 没有找到目标值
}
// ArrayList.sort.test.js
let arr = new ArrayList(16);
console.log("顺序查找");
arr.init();
arr.shuffle();
console.log(arr.toString());
console.log(arr.sequentialSearch(8));
console.log("二分查找");
arr.init();
arr.sort();
console.log(arr.toString());
console.log(arr.binarySearch(8));