很多人学数据结构时,总觉得它是纸上谈兵,但今天要告诉你:无论是写代码还是调系统,数据结构和算法都是决定你程序性能的隐形操盘手。理解了它们,你才能写出真正高效、优雅的代码。
java -version
数据结构是程序的骨架
数据结构说白了就是计算机存数据的方式,不同的存法决定了数据能被怎么用。数组把所有元素排成一排,想找第三个直接去第三个位置拿,效率极高,但要在中间插个新元素就得把后面全挪动,代价很大。
链表则完全相反,每个元素都记着下一个元素的位置,像寻宝游戏一样。插入删除只需改改指针指向,但想找第几个元素必须从头一个个数过去。2026年的今天,内存越来越便宜,但CPU缓存命中率成了关键,连续存储的数组往往比链表跑得快。
图结构无处不在
你每天用的社交软件,朋友关系就是用图来存的。每个人是一个顶点,互相关注就是一条边。微信的好友推荐功能,背后就是图的遍历算法在计算你和陌生人之间有多少共同好友。
public class BubbleSort {
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length == 0) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j arr[j + 1]) {
// 交换arr[j]和arr[j + 1]
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
public static void main(String[] args) {
int[] array = {64, 34, 25, 12, 22, 11, 90};
bubbleSort(array);
for (int value : array) {
System.out.print(value + " ");
}
}
}
地图导航也是图的经典应用。高德地图把路口作为顶点,道路作为边,再用 Dijkstra 算法找出最短路径。2025年高德公布的数据显示,他们的路径规划算法每天要处理超过100亿次请求,背后全是图结构在支撑。
public class SelectionSort {
public static void selectionSort(int[] arr) {
if (arr == null || arr.length == 0) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 将找到的最小值和i位置所在的值进行交换
if (minIndex != i) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
public static void main(String[] args) {
int[] array = {64, 25, 12, 22, 11};
selectionSort(array);
for (int value : array) {
System.out.print(value + " ");
}
}
}
排序算法不只是面试题
public class InsertionSort {
public static void insertionSort(int[] arr) {
if (arr == null || arr.length == 0) {
return;
}
for (int i = 1; i = 0 && arr[j] > current) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = current;
}
}
public static void main(String[] args) {
int[] array = {9, 3, 1, 5, 13};
insertionSort(array);
for (int value : array) {
System.out.print(value + " ");
}
}
}
很多人觉得工作后根本不用自己写排序,直接调库就行。但理解排序原理能帮你做出更好的技术选型。比如处理海量日志数据时,Java 的 Collections.sort 用的是 TimSort,它结合了归并和插入排序的优势。
冒泡排序虽然效率低,但在数据基本有序的情况下表现不错。选择排序无论数据什么样都得比较那么多次,稳定但慢。插入排序在数据量小时反而比快排快,所以很多高级排序算法在递归到小数组时会改用插入排序。
搜索算法决定响应速度
你在淘宝搜索框输入商品,一秒内得到结果,背后可能是二分查找在起作用。但二分查找要求数据必须有序,这就要求数据库建立索引时付出排序的代价。MySQL 的 B+树索引就是专门为快速查找设计的。
public int linearSearch(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
if (array[i] == target) {
return i; // 找到目标元素,返回索引
}
}
return -1; // 未找到目标元素,返回-1
}
图的遍历更是搜索引擎的核心。百度蜘蛛爬取网页时用的就是广度优先搜索,先爬首页,再爬首页上的链接,一层层扩散开去。2025年百度披露他们抓取的网页数量超过 5000 亿,遍历算法稍有低效,整个系统就会瘫痪。
public int binarySearch(int[] array, int target) {
int left = 0;
int right = array.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (array[mid] == target) {
return mid; // 找到目标元素,返回索引
} else if (array[mid] < target) {
left = mid + 1; // 在右半部分查找
} else {
right = mid - 1; // 在左半部分查找
}
}
return -1; // 未找到目标元素,返回-1
}
高级数据结构提升效率
堆这种结构你可能不常用,但 Java 的 PriorityQueue 就是用它实现的。任务调度系统里,高优先级的任务需要先执行,如果用数组每次都得全扫描,用堆就能 O(1) 时间拿到最高优先级任务。
红黑树和 AVL 树都是为了解决二叉搜索树会变成链表的问题。Java 8 的 HashMap 在链表长度超过 8 时转为红黑树,就是怕频繁哈希冲突导致查找变慢。TreeMap 干脆直接用红黑树,保证所有操作都在 O(log n) 时间内完成。
import java.util.*;
public class Graph {
private int vertices; // 图的顶点数
private LinkedList[] adjLists; // 邻接表
public Graph(int vertices) {
this.vertices = vertices;
adjLists = new LinkedList[vertices];
for (int i = 0; i < vertices; i++) {
adjLists[i] = new LinkedList();
}
}
public void addEdge(int source, int destination) {
adjLists[source].add(destination);
}
public void DFS(int startVertex) {
boolean[] visited = new boolean[vertices];
DFSUtil(startVertex, visited);
}
private void DFSUtil(int vertex, boolean[] visited) {
visited[vertex] = true;
System.out.print(vertex + " ");
Iterator iterator = adjLists[vertex].listIterator();
while (iterator.hasNext()) {
int nextVertex = iterator.next();
if (!visited[nextVertex]) {
DFSUtil(nextVertex, visited);
}
}
}
}
算法思想才是核心
动态规划看起来难,但它就是记住已经算过的结果,避免重复劳动。比如计算斐波那契数列,递归会重复算无数次,用数组存中间结果就能直接加速几百倍。微信的步数排行榜排名计算,也得用动态规划思想优化。
import java.util.*;
public class Graph {
// ... (前面的代码不变)
public void BFS(int startVertex) {
boolean[] visited = new boolean[vertices];
LinkedList queue = new LinkedList();
visited[startVertex] = true;
queue.add(startVertex);
while (queue.size() != 0) {
startVertex = queue.poll();
System.out.print(startVertex + " ");
Iterator iterator = adjLists[startVertex].listIterator();
while (iterator.hasNext()) {
int nextVertex = iterator.next();
if (!visited[nextVertex]) {
visited[nextVertex] = true;
queue.add(nextVertex);
}
}
}
}
}
回溯算法就是有策略地穷举。写数独求解程序时,每个空格尝试填 1 到 9,不行就退回来换一个,这就是回溯。虽然听着笨,但在组合爆炸的问题里,加上剪枝就是最实用的解法。
public class GraphMatrix {
private int[][] matrix;
private int vertices;
public GraphMatrix(int vertices) {
this.vertices = vertices;
matrix = new int[vertices][vertices];
}
public void addEdge(int source, int destination) {
matrix[source][destination] = 1;
matrix[destination][source] = 1; // 对于无向图
}
public void printMatrix() {
for (int i = 0; i < vertices; i++) {
for (int j = 0; j < vertices; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
}
你在实际项目中用过哪种数据结构或算法解决了棘手问题?欢迎在评论区分享你的经历,觉得文章有用的话点个赞让更多人看到!
public class GraphList {
private LinkedList[] adjLists;
private int vertices;
public GraphList(int vertices) {
this.vertices = vertices;
adjLists = new LinkedList[vertices];
for (int i = 0; i < vertices; i++) {
adjLists[i] = new LinkedList();
}
}
public void addEdge(int source, int destination) {
adjLists[source].add(destination);
}
public void printGraph() {
for (int i = 0; i < vertices; i++) {
System.out.print("Vertex " + i + ":");
Iterator iterator = adjLists[i].listIterator();
while (iterator.hasNext()) {
System.out.print(" -> " + iterator.next());
}
System.out.println();
}
}
}

