问题引入:
怎么辨别下面两个链表的区别?,他们的结点数都相同
方法:快慢指针
什么是快慢指针?
顾名思义,使用两个指针,一个的位移距离比另一个要大
怎么使用快慢指针判断链表是否有环?
令两个指针都位于链表头结点,处于头指针的位置,快指针每次向后移动两个结点的位置,慢指针每次移动一个结点的位置,如果两个指针相遇了,证明有环
区分:头结点,首结点
- 头结点是为了操作链表方便而设立的结点,里面一般不存放数据
- 首结点才是第一个数据的存放点
下图是每一步的执行过程,在第七步,两个指针指向了同一个结点,证明了这个链表有环
当链表没有环的时候,快指针必然会指向NULL,因为尾结点的指针指向的就是NULL
NULL 表示空
问题拓展:
1.怎么求出环的长度?
- 增加一个变量记录下指针的移动次数
- 当快指针和慢指针相遇的时候,快指针比慢指针多走了一个环的长度,相当于数学中的追及问题,快的一方追上慢的一方的时候,多跑了一圈
- 环的长度 = 速度差(快的和慢的每次移动距离的差值)* 移动的次数
- 环的长度相当于路程 ,速度差相当于速度 , 移动次数相当于时间 ,所以,路程等于速度乘以时间
上图中,序号1 是初始状态,到序号7 的时候,总共经历了六步(2,3,4,5,6,7),而速度差和移动次数的乘积正好是6,符合环的长度为6
2.如何判断环的起点(尾部连到的是哪个结点)?
- 把一个指针放回头结点
- 另一个指针保留在相遇的那个结点
- 令两个指针同时开始,每一次都只移动一个结点,再一次相遇的时候,便是这个环的起点
到第二步的时候,a , b 两个指针再一次相遇,而他们再一次相遇的这个点正好是这个环的起点(下面一行最左边的那个点为链表的头结点)