基本搜索/查找算法

线性搜索(Linear Search)

线性搜索是一种简单直观的搜索算法,它逐个遍历数组中的元素,直到找到目标元素或遍历完整个数组。

/**
 * 线性查找函数
 *
 * @param arr 目标数组
 * @param target 目标元素
 * @returns 返回目标元素在数组中的索引,若不存在则返回-1
 */
function linearSearch(arr, target) {
  // 遍历数组
  for (let i = 0; i < arr.length; i++) {
      // 如果当前元素等于目标元素
      if (arr[i] === target) {
          // 返回目标元素的索引
          return i; // 找到目标元素,返回索引
      }
  }
  // 如果循环结束仍未找到目标元素
  // 返回-1表示目标元素不存在
  return -1; // 目标元素不存在,返回-1
}

let arr = [64, 34, 25, 12, 22, 11, 90];
let target = 22;
let index = linearSearch(arr, target);
if (index !== -1) {
  console.log("线性搜索:元素", target, "的索引为", index);
} else {
  console.log("线性搜索:元素", target, "不存在于数组中");
}

.二分搜索(Binary Search)

二分搜索是一种高效的搜索算法,它要求被搜索的数组已经有序。算法通过不断将搜索区间分成两半,并比较目标值与中间值的大小关系来确定目标值可能在哪一半中,从而缩小搜索范围。

/**
 * 二分查找算法
 *
 * @param arr 目标数组
 * @param target 目标元素
 * @returns 返回目标元素在数组中的索引,若不存在则返回-1
 */
function binarySearch(arr, target) {
  let low = 0;
  let high = arr.length - 1;
  while (low <= high) {
      let mid = Math.floor((low + high) / 2);
      // 如果中间元素等于目标元素,返回中间元素的索引
      if (arr[mid] === target) {
          return mid; // 找到目标元素,返回索引
      // 如果中间元素小于目标元素,更新 low 为 mid + 1
      } else if (arr[mid] < target) {
          low = mid + 1;
      // 如果中间元素大于目标元素,更新 high 为 mid - 1
      } else {
          high = mid - 1;
      }
  }
  // 目标元素不存在于数组中,返回 -1
  return -1; // 目标元素不存在,返回-1
}

let arr = [11, 12, 22, 25, 34, 64, 90];
let target = 22;
let index = binarySearch(arr, target);
if (index !== -1) {
  console.log("二分搜索:元素", target, "的索引为", index);
} else {
  console.log("二分搜索:元素", target, "不存在于数组中");
}

广度优先搜索(BFS)

广度优先搜索是一种用于图和树等数据结构中的搜索算法,它从起始顶点开始,逐层扩展搜索,先访问起始顶点的所有邻接顶点,然后再逐层访问它们的邻接顶点,直到找到目标顶点或遍历完整个图或树。

class Graph {
  /**
   * 构造函数
   */
  constructor() {
    // 创建一个空的Map对象,用于存储邻接表
    this.adjList = new Map();
  }

  /**
   * 添加一个顶点
   *
   * @param vertex 要添加的顶点
   */
  addVertex(vertex) {
    // 判断顶点是否已经存在于邻接表中
    if (!this.adjList.has(vertex)) {
      // 如果不存在,则在邻接表中添加该顶点,并将其对应的值初始化为空数组
      this.adjList.set(vertex, []);
    }
  }

  /**
   * 添加边
   *
   * @param vertex 顶点
   * @param neighbor 邻接点
   */
  addEdge(vertex, neighbor) {
    // 将邻居节点添加到当前节点的邻接表中
    this.adjList.get(vertex).push(neighbor);
    // 由于是无向图,所以需要将当前节点也添加到邻居节点的邻接表中
    this.adjList.get(neighbor).push(vertex); // 无向图需要加上这一行
  }

  /**
   * 广度优先搜索算法
   *
   * @param start 起始节点
   * @returns 返回从起始节点开始的广度优先搜索遍历结果
   */
  bfs(start) {
    // 创建一个队列,将起始节点放入队列中
    const queue = [start];
    // 创建一个空对象用于记录已访问的节点
    const visited = {};
    // 创建一个空数组用于存储结果
    const result = [];

    // 将起始节点标记为已访问
    visited[start] = true;

    // 当队列不为空时,循环执行以下操作
    while (queue.length) {
      // 从队列中取出第一个节点
      const vertex = queue.shift();
      // 将该节点加入结果数组中
      result.push(vertex);

      // 获取该节点的邻居节点
      const neighbors = this.adjList.get(vertex);

      // 遍历邻居节点
      for (const neighbor of neighbors) {
        // 如果该邻居节点未被访问过
        if (!visited[neighbor]) {
          // 将其标记为已访问
          visited[neighbor] = true;
          // 将该邻居节点加入队列中
          queue.push(neighbor);
        }
      }
    }

    // 返回结果数组
    return result;
  }
}

// 创建一个新的图对象
const graph = new Graph();


graph.addVertex('A'); // 向图中添加节点 'A'
graph.addVertex('B');// 向图中添加节点 'B'
graph.addVertex('C');// 向图中添加节点 'C'
graph.addVertex('D');// 向图中添加节点 'D'
graph.addVertex('E');// 向图中添加节点 'E'


graph.addEdge('A', 'B');// 在节点 'A' 和 'B' 之间添加一条边
graph.addEdge('A', 'C');// 在节点 'A' 和 'C' 之间添加一条边
graph.addEdge('B', 'D');// 在节点 'B' 和 'D' 之间添加一条边
graph.addEdge('C', 'E');// 在节点 'C' 和 'E' 之间添加一条边

// 调用广度优先搜索方法,从节点 'A' 开始遍历图,并打印结果
console.log('BFS:', graph.bfs('A'));

深度优先搜索(DFS)

深度优先搜索也是一种用于图和树等数据结构中的搜索算法,它从起始顶点开始,尽可能深地搜索图的路径,直到找到目标顶点或者到达图的最大深度。在搜索过程中,如果碰到已经访问过的顶点或者搜索到了叶子节点,则回溯到上一个顶点进行继续搜索。

class Graph {
  /**
   * 构造函数
   */
  constructor() {
    // 创建一个空的无向图
    this.adjList = new Map();
  }

  /**
   * 向邻接表中添加顶点
   *
   * @param vertex 要添加的顶点
   */
  addVertex(vertex) {
    // 判断顶点是否已经存在于邻接表中
    if (!this.adjList.has(vertex)) {
      // 如果不存在,则在邻接表中添加该顶点,并设置其对应的邻接节点列表为空数组
      this.adjList.set(vertex, []);
    }
  }

  /**
   * 添加一条边到无向图中
   *
   * @param vertex 顶点
   * @param neighbor 邻居顶点
   */
  addEdge(vertex, neighbor) {
    // 向顶点的邻接表中添加邻居顶点
    this.adjList.get(vertex).push(neighbor);
    // 无向图需要加上这一行,将邻居顶点也添加到当前顶点的邻接表中
    this.adjList.get(neighbor).push(vertex); // 无向图需要加上这一行
  }

  /**
   * DFS辅助函数,用于遍历从指定节点开始的所有可达节点
   *
   * @param vertex 当前遍历的节点
   * @param visited 记录节点是否被访问过的数组
   * @param result 存储遍历结果的数组
   */
  dfsHelper(vertex, visited, result) {
    // 将当前顶点标记为已访问
    visited[vertex] = true;
    // 将当前顶点加入结果列表
    result.push(vertex);
    // 获取当前顶点的邻接表
    const neighbors = this.adjList.get(vertex);
    // 遍历邻接表中的每个邻居顶点
    for (const neighbor of neighbors) {
      // 如果邻居顶点未被访问过
      if (!visited[neighbor]) {
        // 递归调用dfsHelper函数,继续遍历邻居顶点的邻接表
        this.dfsHelper(neighbor, visited, result);
      }
    }
  }

  /**
   * 深度优先搜索算法
   *
   * @param start 开始节点
   * @returns 返回从start开始的所有路径
   */
  dfs(start) {
    // 创建一个空对象用于记录访问过的节点
    const visited = {};
    // 创建一个空数组用于存储结果
    const result = [];
    // 调用深度优先搜索辅助函数
    this.dfsHelper(start, visited, result);
    // 返回结果
    return result;
  }
}

// 创建一个新的图对象
const graph = new Graph();

graph.addVertex('A');// 向图中添加顶点 'A'
graph.addVertex('B');// 向图中添加顶点 'B'
graph.addVertex('C');// 向图中添加顶点 'C'
graph.addVertex('D');// 向图中添加顶点 'D'
graph.addVertex('E');// 向图中添加顶点 'E'


graph.addEdge('A', 'B');// 在顶点 'A' 和 'B' 之间添加一条边
graph.addEdge('A', 'C');// 在顶点 'A' 和 'C' 之间添加一条边
graph.addEdge('B', 'D');// 在顶点 'B' 和 'D' 之间添加一条边
graph.addEdge('C', 'E');// 在顶点 'C' 和 'E' 之间添加一条边

// 使用深度优先搜索算法从顶点 'A' 开始遍历图,并打印出遍历的结果
console.log('DFS:', graph.dfs('A'));

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿online

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

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

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

打赏作者

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

抵扣说明:

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

余额充值