思路:
1、快慢引用 fast 一次跑两个,slow一次跑一个两者相遇有环,但相遇点不一定是入口点,如何证明是不是入口点? 快路径长度=2慢路径长度
2、代码实现
public class Link<T extends Comparable<T>> {
private Entry<T> headEntry;
private Entry<T> tailEntry;//标记尾部
public Entry<T> getEntry(T value){
for(Entry<T> p = headEntry;p!=null;p=p.getNext()){
if(p.getValue().compareTo(value) ==0){
return p;
}
}
return null;
}
public void addHead(T value){
Entry<T> p=new Entry<>(value);
//空链表
if(headEntry==null){
headEntry=p;
tailEntry=p; //标记尾巴
}else {
p.setNext(headEntry);
headEntry=p;//新链表起始位置
}
}
public void addTail(T value){
Entry<T> newEntry=new Entry<>(value);
if(headEntry ==null){
headEntry= newEntry;
tailEntry= newEntry;
}else {
tailEntry.setNext(newEntry);
tailEntry=newEntry;
}
}
public void removeHead(){
if(headEntry==null){
return;
}
headEntry.setValue(null);
headEntry=headEntry.getNext();
if(headEntry==null){
tailEntry=null;
}
}
public void removeTail(){
if (headEntry==null){
return;
}
if(headEntry.getNext()==null){
headEntry=null;
tailEntry=null;
return;
}
tailEntry.setValue(null);//防止内存泄漏
//为尾巴找前驱
Entry<T> beforeTail=headEntry;
for(;beforeTail.getNext().getNext()!=null;beforeTail=beforeTail.getNext()){
;
}
//找到尾巴前驱
tailEntry=beforeTail;
tailEntry.setNext(null);//新尾部结点next=null
beforeTail.setNext(null);
}
public void removeValue(T value){
if(headEntry==null){
return;
}
if(headEntry.getValue().compareTo(value)==0){
headEntry.setValue(null);//防止内存泄漏
headEntry=headEntry.getNext();
if(tailEntry==headEntry){
tailEntry=null;
}
return;
}
//p保存要删结点的前驱结点
for(Entry<T>p=headEntry;p.getNext()!=null;p=p.getNext()){
if(p.getNext().getValue().compareTo(value)==0){
p.getNext().setValue(null);//防止内存泄漏
p.setNext(p.getNext().getNext());
tailEntry=p;//此时更新新尾部
break;
}
}
}
public void show(){
for(Entry p=headEntry;p!=null;p=p.getNext()){
System.out.println(p.getValue()+" ");
}
System.out.println();
}
private int getLength(){
int count =0;
for(Entry<T> p=headEntry;p!=null;p=p.getNext()){
count++;
}
return count;
}
public Entry<T> isCircle(){
Entry<T> fast =headEntry;
Entry<T> slow =headEntry;
do{
if(fast==null||fast.getNext()==null){
return null;
}
slow=slow.getNext();
fast=fast.getNext().getNext();
}while (fast!=slow);
return slow;
}
//输出环的入口结点:当前链表环的入口结点
public Entry<T> getCircleMeetEntry(){
Entry<T> meet=isCircle();
if(meet ==null){
return null;
}
Entry<T> p=headEntry;
Entry<T> q=meet;
while (p!=q){
p=p.getNext();
q=q.getNext();
}
return p;
}
}