环形链表是另一种形式的链式存储结构。它的特点是链表中最后一个结点的指针域指向头结点,整个链表形成一个环。
由于环形链表的末尾节点指向头节点,因此,我们可以仅使用一个指针来存储链表地址,而不需要使用两个指针。
例如,在 React 中,useState
的 Hook 就是基于环形链表实现的。当有多个更新任务时,会有一个 queue.pending
指针来指向环形链表的末尾节点,如下所示。
通过这样的方式,我们可以通过末尾节点快速访问首节点
1// 尾部节点2tail = queue.pending3// 首节点4head = queue.pending.next
代码如下
10// 创建新节点20const update = {30next: null,40action: () => {}50}6070// 将新节点添加到末尾80const tail = queue.pending // 尾部节点90const head = queue.pending.next // 首节点1011// 将新节点添加到尾部12tail.next = update13update.next = head14queue.pending = update
图例演示如下
创建一个新节点
让老的尾部节点指向新节点
让新节点指向首节点
让 queue.pending
指向新节点
循环链表的遍历需要特殊处理一下,一不小心可能会陷入无限循环当中,因此,我们要巧妙的设计一个缓存指针,来记录当前遍历到的节点。如果该节点与循环开始的节点相同,则推出循环。
代码如下
1let current = queue.pending23while (true) {4current = current.next5if (current === queue.pending) {6break7}8}
如果我们已知链表的长度,也可以使用 for
循环来遍历链表。
1for (let i = 0; i < length; i++) {2current = current.next3}
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
示例 1
1输入:head = [3,2,0,-4], pos = 12输出:true3解释:链表中有一个环,其尾部连接到第二个节点。
示例 2
1输入:head = [1,2], pos = 02输出:true3解释:链表中有一个环,其尾部连接到第一个节点。
示例 3
1输入:head = [1], pos = -12输出:false3解释:链表中没有环。