常用的数据结构

134 阅读5分钟

数据结构是计算机存储和组织数据的方式,选择合适的数据结构可以极大地提高程序的效率和性能。下面我将一些最常用的数据结构进行分类介绍

1. 线性结构

1.1 数组

  • 特点:在内存中占据一段连续的空间。通过索引(下标)可以快速访问任意位置的元素(时间复杂度 O(1))。但大小固定,插入和删除元素效率较低(平均需要移动元素,时间复杂度 O(n))。
  • 场景:需要频繁随机访问元素、已知数据规模或规模变化不大的情况。

1.2 链表

  • 特点:通过“指针”将一组零散的内存块串联起来。插入和删除效率高(只需要改变指针指向,时间复杂度 O(1))。但访问元素需要从头遍历(时间复杂度 O(n)),且需要额外的空间存储指针。

  • 常见变种

    • 单向链表:每个节点只指向下一个节点。
    • 双向链表:每个节点指向前一个和后一个节点,支持双向遍历。
    • 循环链表:尾节点指向头节点,形成一个环。
  • 场景:频繁进行插入和删除操作、不确定数据规模的情况(如实现队列、LRU缓存)。

1.3 

  • 特点:一种后进先出的操作受限的线性表。只允许在一端(栈顶)进行插入(入栈/Push)和删除(出栈/Pop)操作。
  • 场景:函数调用栈、表达式求值、括号匹配、浏览器前进/后退功能。

1.4 队列

  • 特点:一种先进先出的操作受限的线性表。只允许在一端(队尾)进行插入(入队/Enqueue),在另一端(队头)进行删除(出队/Dequeue)。

  • 常见变种

    • 双端队列:两端都允许进行插入和删除操作。
    • 优先队列:出队顺序由元素的“优先级”决定,通常用来实现。
  • 场景:任务调度、消息队列、广度优先搜索(BFS)。

2. 树形结构

2.1 二叉树

  • 特点:每个节点最多有两个子节点(左子节点和右子节点)。

  • 常见类型

    • 二叉搜索树:左子树所有节点的值 < 根节点的值 < 右子树所有节点的值。其中平衡二叉搜索树(如AVL树、红黑树)保证了查询、插入、删除的时间复杂度都是 O(log n),效率极高。
    • :一种完全二叉树。最大堆的父节点值总大于等于子节点;最小堆的父节点值总小于等于子节点。
  • 场景

    • BST:用于实现高效的动态数据查找(如数据库索引)。
    • :实现优先队列、堆排序、Top K问题。

2.2 字典树

  • 特点:专门用于处理字符串。利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。
  • 场景:搜索引擎的自动补全、拼写检查、IP路由表。

2.3 B+ 树

  • 特点:一种多路平衡搜索树,一个节点可以有多个子节点。大大降低了树的高度,减少了磁盘I/O次数。
  • 场景数据库和文件系统的索引。几乎所有主流数据库(如MySQL)的索引都使用B+树。

3. 散列表(哈希表)

  • 特点:通过哈希函数将键映射到数组中的一个位置来进行访问。理想情况下,查找、插入、删除操作的时间复杂度都可以接近 O(1)
  • 挑战:需要处理哈希冲突(不同的键映射到同一位置),常用解决方法有链地址法(用链表存储冲突元素)和开放地址法
  • 场景:需要极快查找速度的场景,如实现字典、缓存(Redis)、集合。

4. 图

  • 特点:由顶点组成,用于表示多对多的复杂关系。

  • 存储方式

    • 邻接矩阵:用一个二维数组表示顶点之间的连接关系。查询快,但稀疏图非常浪费空间。
    • 邻接表:为每个顶点维护一个链表,存储与其相连的顶点。节省空间,是更常用的方式。
  • 场景:社交网络(顶点是用户,边是好友关系)、地图导航(顶点是地点,边是道路)、推荐系统。

5. 总结

以上就是常用的数据结构,可能在实际的开发中,我们百分之九十只会用到线性结构,接下来我们对上面的数据结构进行一个总结和对比

数据结构特点优点缺点典型应用
数组连续内存,索引访问随机访问快大小固定,插入删除慢任何需要随机访问的场景
链表离散内存,通过指针连接插入删除快随机访问慢队列,LRU缓存,链表反转
后进先出实现简单功能受限函数调用,括号匹配
队列先进先出实现简单功能受限任务调度,BFS
哈希表键值对,哈希函数查找插入删除快无序,可能有哈希冲突字典,缓存,集合
二叉搜索树有序,左-根-右查找插入删除快可能会退化为链表动态数据查找
父节点总 大于/小于 子节点快速获取最大最小值其他操作相对慢优先队列
顶点和边建模复杂关系算法复杂社交网络,路径规划

选择数据结构的核心思路是:分析你的核心操作(是查找多,还是插入删除多?是否需要有序?),然后选择能让你核心操作效率最高的那一个。

那么后面我将从代码层面出发,一个一个去实现上述的数据结构