# 线性搜索

比较次数: 0

# 算法原理

线性搜索(Linear Search)是最简单的搜索算法,它按顺序扫描列表中的每个元素,直到找到所需的元素或者搜索完整个列表。这种方法虽然简单,但对于大型数据集来说效率较低。

# 算法步骤

  1. 从列表的第一个元素开始
  2. 依次比较每个元素与要查找的值
  3. 如果找到匹配的元素,返回其索引
  4. 如果遍历完整个列表都没有找到,返回表示未找到的标记(如-1)

# 代码实现

function linearSearch(arr, target) {
  const len = arr.length;
  
  for (let i = 0; i < len; i++) {
    // 找到目标元素,返回其索引
    if (arr[i] === target) {
      return i;
    }
  }
  
  // 未找到目标元素,返回-1
  return -1;
}

// 支持自定义比较函数的版本
function linearSearchWithComparator(arr, target, comparator) {
  const len = arr.length;
  
  for (let i = 0; i < len; i++) {
    if (comparator(arr[i], target)) {
      return i;
    }
  }
  
  return -1;
}

# 复杂度分析

# 时间复杂度

  • 最好情况:O(1),目标元素在列表的开始位置
  • 最坏情况:O(n),目标元素在列表的末尾或不存在
  • 平均情况:O(n),需要检查一半的元素

# 空间复杂度

  • O(1),只需要常量空间存储循环变量

# 算法特点

# 优点

  • 实现简单,容易理解
  • 适用于小规模数据
  • 不需要数据有序
  • 对数据结构没有特殊要求

# 缺点

  • 时间复杂度较高
  • 对于大规模数据效率低
  • 不适合频繁查找操作

# 适用场景

  1. 小规模数据集
  2. 无序数据集
  3. 只需要进行一次性查找
  4. 数据集经常变化,维护有序状态成本高

# 优化方案

  1. 哨兵优化:在数组末尾添加目标值,减少边界检查
  2. 跳跃搜索:每次跳过固定步长,适用于有序数组
  3. 二分搜索:如果数据有序,可以使用更高效的二分搜索
// 使用哨兵优化的线性搜索
function sentinelLinearSearch(arr, target) {
  const len = arr.length;
  const last = arr[len - 1];  // 保存最后一个元素
  arr[len - 1] = target;      // 设置哨兵
  
  let i = 0;
  while (arr[i] !== target) {
    i++;
  }
  
  arr[len - 1] = last;  // 恢复最后一个元素
  
  if (i < len - 1 || arr[len - 1] === target) {
    return i;
  }
  return -1;
}

// 跳跃搜索
function jumpSearch(arr, target) {
  const len = arr.length;
  const step = Math.floor(Math.sqrt(len));
  
  // 找到可能包含目标值的块
  let prev = 0;
  while (arr[Math.min(step, len) - 1] < target) {
    prev = step;
    step += Math.floor(Math.sqrt(len));
    if (prev >= len) {
      return -1;
    }
  }
  
  // 在块内进行线性搜索
  while (arr[prev] < target) {
    prev++;
    if (prev === Math.min(step, len)) {
      return -1;
    }
  }
  
  if (arr[prev] === target) {
    return prev;
  }
  
  return -1;
}

# 实际应用

  1. 在小型数据库中查找记录
  2. 在未排序的数组中查找元素
  3. 在链表等只能顺序访问的数据结构中查找元素
  4. 作为其他搜索算法的基础或备选方案