单链表、双链表、循环单链表、循环双链表、哈希表、hashmap

本文详细介绍了链表的不同类型及其特点,并深入探讨了哈希表的工作原理、哈希函数的重要性以及解决哈希冲突的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单链表:拥有指向下一节点的指针。查找元素需要从头结点遍历

双链表:拥有指向上一节点和下一节点的指针。相对于单链表,在找当前节点的前一节点时比较方便,占用空间比单链表大。

单循环链表:单链表中,从一已知结点出发,只能访问到该结点及其后续结点,无法找到该结点之前的其它结点。而在单循环链表中,从任一结点出发都可访问到表中所有结点,这一优点使某些运算在单循环链表上易于实现。

双循环链表:可以从任何结点开始任意向前向后双向访问。

单链表和单循环链表:只能在当前结点后插入和删除。


双链表:可以在当前结点前面或者后面插入,可以删除前趋和后继(包括结点自己)。


存储:单链表和单循环链表存储密度大于双链表。

哈希表:在哈希表中进行添加,删除,查找等操作,性能十分之高,不考虑哈希冲突的情况下,仅需一次定位即可完成,时间复杂度为O(1)。我们要新增或查找某个元素,我们通过把当前元素的关键字 通过某个函数映射到数组中的某个位置,通过数组下标一次定位就可完成操作。

        存储位置 = f(关键字)

  其中,这个函数f一般称为哈希函数,这个函数的设计好坏会直接影响到哈希表的优劣。例如:

        

当我们对某个元素进行哈希运算,得到一个存储地址,然后要进行插入的时候,发现已经被其他元素占用了,其实这就是所谓的哈希冲突,也叫哈希碰撞。数组是一块连续的固定长度的内存空间,再好的哈希函数也不能保证得到的存储地址绝对不发生冲突。哈希冲突的解决方案有多种:开放定址法(发生冲突,继续寻找下一块未被占用的存储地址),再散列函数法,链地址法,而HashMap即是采用了链地址法,也就是数组+链表的方式,

hashmap:简单来说,HashMap由数组+链表组成的,数组是HashMap的主体链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

### 链表数据结构的常见使用场景 链表作为一种常见的线性数据结构,在许多应用场景中具有独特的优势。以下是链表的一些主要使用场景: #### 1. 动态内存分配 由于链表支持动态扩展和收缩,它非常适合于需要频繁插入和删除操作的情况。例如,在某些实时系统中,可能无法预先知道所需存储的数据量大小,此时可以利用链表来动态调整存储容量[^1]。 #### 2. 实现其他高级数据结构 链表常被用来作为构建更复杂数据结构的基础组件。例如: - **栈** 和 **队列** 的底层实现可以通过双端链表完成,从而提供高效的插入和移除功能[^3]。 - 双向链表还可以用于实现哈希表中的桶(bucket),尤其是在处理冲突时能够快速定位并更新键值对。 #### 3. 文件系统的目录管理 在文件系统设计中,目录项通常采用某种形式的链接方式组织起来,以便高效地管理和检索子目录以及文件信息。这种情况下,单链表或多级嵌套的形式都可以很好地满足需求[^2]。 #### 4. 缓存机制 (LRU Cache) 最近最少使用缓存算法(LRU - Least Recently Used) 中经常需要用到双向链表配合哈希映射一起工作。通过维护一个按访问顺序排列节点组成的环形或者非环形双向链表,再加上一张记录key-value关系的hashmap,就可以轻松实现在固定大小范围内保持最新使用的条目始终处于头部位置的同时淘汰掉最久未被触及的那个项目[^2]. #### 5. 图像编辑软件中的撤销/重做功能 为了给用户提供便捷的操作体验,图像编辑类应用程序普遍具备Undo(撤消)/Redo(恢复)能力。这类特性背后往往依赖于基于事件历史记录所形成的链条式保存策略;而这些链条则恰好可以用到简单的单向或是更加灵活复杂的双向甚至循环版本类型的链表来进行表达与追踪变化轨迹. ```python class Node: def __init__(self, data=None): self.data = data self.next = None class LinkedList: def __init__(self): self.head = None def append(self, data): new_node = Node(data) if not self.head: self.head = new_node return last = self.head while last.next: last = last.next last.next = new_node ``` 以上展示了一个基本的单链表示例代码片段,展示了如何创建一个新的节点并将该节点追加至现有列表末端的过程。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值