以下是四种常见搜索算法的Java实现及详细解析,包含代码示例和关键特性对比:
一、算法概览
算法 | 时间复杂度 | 空间复杂度 | 适用场景 | 核心特点 |
---|---|---|---|---|
线性搜索 | O(n) | O(1) | 无序小规模数据 | 简单直接,无需预处理 |
二分搜索 | O(log n) | O(1) | 有序静态数据 | 高效但需先排序 |
深度优先搜索(DFS) | O(V+E) | O(V) | 路径探索/拓扑排序 | 递归/栈实现,可能非最短路径 |
广度优先搜索(BFS) | O(V+E) | O(V) | 最短路径/层级遍历 | 队列实现,保证最短路径 |
二、算法详解与Java实现
1. 线性搜索(Linear Search)
public class LinearSearch {
public static int search(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return i; // 找到目标返回索引
}
}
return -1; // 未找到
}
public static void main(String[] args) {
int[] arr = {5, 3, 8, 2, 9};
int target = 8;
int index = search(arr, target);
System.out.println("目标索引: " + index); // 输出: 2
}
}
- 适用场景:小型无序数据集或单次查询。
- 关键点:无需预处理,实现简单但效率低。
2. 二分搜索(Binary Search)
import java.util.Arrays;
public class BinarySearch {
public static int search(int[] arr, int target) {
Arrays.sort(arr); // 必需先排序!
int left = 0, right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 防溢出
if (arr[mid] == target) return mid;
else if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
public static void main(String[] args) {
int[] arr = {2, 5, 8, 12, 16};
int target = 12;
int index = search(arr, target);
System.out.println("目标索引: " + index); // 输出: 3
}
}
- 适用场景:大型静态有序数据集(如数据库索引)。
- 关键点:必须预排序,效率极高但无法处理动态数据。
3. 深度优先搜索(DFS)
import java.util.*;
public class DFS {
static class Graph {
private int V;
private LinkedList<Integer>[] adj;
Graph(int v) {
V = v;
adj = new LinkedList[v];
for (int i = 0; i < v; i++) {
adj[i] = new LinkedList<>();
}
}
void addEdge(int v, int w) {
adj[v].add(w);
}
void dfs(int start) {
boolean[] visited = new boolean[V];
dfsUtil(start, visited);
}
private void dfsUtil(int v, boolean[] visited) {
visited[v] = true;
System.out.print(v + " "); // 访问节点
for (int neighbor : adj[v]) {
if (!visited[neighbor]) {
dfsUtil(neighbor, visited); // 递归深入
}
}
}
}
public static void main(String[] args) {
Graph g = new Graph(4);
g.addEdge(0, 1); g.addEdge(0, 2);
g.addEdge(1, 3); g.addEdge(2, 3);
System.out.print("DFS遍历顺序: ");
g.dfs(0); // 输出: 0 1 3 2
}
}
- 适用场景:路径存在性检测、回溯问题(如迷宫求解)。
- 关键点:使用递归/栈,可能陷入深度分支,不保证最短路径。
4. 广度优先搜索(BFS)
import java.util.*;
public class BFS {
static class Graph {
private int V;
private LinkedList<Integer>[] adj;
Graph(int v) {
V = v;
adj = new LinkedList[v];
for (int i = 0; i < v; i++) {
adj[i] = new LinkedList<>();
}
}
void addEdge(int v, int w) {
adj[v].add(w);
}
void bfs(int start) {
boolean[] visited = new boolean[V];
Queue<Integer> queue = new LinkedList<>();
visited[start] = true;
queue.add(start);
while (!queue.isEmpty()) {
int current = queue.poll();
System.out.print(current + " "); // 访问节点
for (int neighbor : adj[current]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.add(neighbor); // 层级扩展
}
}
}
}
}
public static void main(String[] args) {
Graph g = new Graph(4);
g.addEdge(0, 1); g.addEdge(0, 2);
g.addEdge(1, 3); g.addEdge(2, 3);
System.out.print("BFS遍历顺序: ");
g.bfs(0); // 输出: 0 1 2 3
}
}
- 适用场景:无权图最短路径、社交网络好友推荐。
- 关键点:使用队列逐层遍历,保证找到最短路径。
三、DFS与BFS遍历过程对比(以图0→1, 0→2, 1→3, 2→3
为例)
- DFS:深度优先 → 沿分支深入到底再回溯(路径:0→1→3→2)。
- BFS:广度优先 → 按层级逐步扩展(路径:0→1→2→3)。
四、选型建议
-
数据规模
- <100元素:线性搜索(简单直接)。
- >1000有序元素:二分搜索(效率飞跃)。
-
数据结构特性
- 图/树结构:优先BFS(求最短路径)或DFS(路径探索)。
- 动态数据:哈希表(平均O(1)查询)。
-
高级优化
- 大规模数据 → 跳表(O(log n)动态更新)。
- 分布式系统 → 一致性哈希(负载均衡)。