目录
如何判环?
如何求环的长度?
如何求环的入口呢?
示例
如何判环?
思路: 利用两个移动速度不同的指针,若在均不为空的情况下相遇,则存在环
如何求环的长度?
思路:若存在环,那么快慢指针从相遇点重新出发到再次相遇的过程中, 一定是慢指针走了一圈,快指针走了两圈, 慢指针所走过的步数即为环的长度
如何求环的入口呢?
推理:
![[数据结构] 单链表如何判环以及求环的长度,入口_数据结构](https://file.cfanz.cn/uploads/png/2022/06/14/3/913X3V7211.png)
所以,我们在相遇点位和链表的起点分别设立两个速度相同的指针,当他们相遇时即在环的入口
示例
其中测试数据的关系如图
![[数据结构] 单链表如何判环以及求环的长度,入口_数据结构_02](https://file.cfanz.cn/uploads/png/2022/06/14/3/25SPb8a86Q.png)
using namespace std;
typedef struct SingleListNode{
    int value;
    SingleListNode* next;
    SingleListNode(int v):value(v),next(NULL){}
}SLNode;
class SingleList{
    public:
        SLNode* phead;
        SingleList();
        bool isCircle(){
            return firstMeet(phead) != NULL;
        }
        int getCircleLenth();
        int getCircleEntrance();
        void headInsert(int value);
    private:
        
        SLNode* firstMeet(SLNode* phead);
};
SingleList::SingleList()
{
    phead = new SLNode(0);
}
void SingleList::headInsert(int value)
{
    SLNode* newNode = new SLNode(value);
    newNode->next = phead->next;
    phead->next = newNode;
}
SLNode* SingleList::firstMeet(SLNode* phead)
{
    SLNode* pslow, *pfast;
    pslow = pfast = phead->next;
    while(pslow && pfast)       //若存在环的话两个工作指针必不会出现空的情况
    {
        pslow = pslow->next;
        pfast = pfast->next ? pfast->next->next : pfast->next;
        if(pslow->value == pfast->value) return pslow;
    }
    return NULL;       
}
int SingleList::getCircleLenth()
{
    SLNode* pfirstMeet = firstMeet(phead);
    
    //无环的情况
    if(!pfirstMeet) return 0;
    SLNode* pslow, *pfast;
    pslow = pfast = pfirstMeet;
    int step = 0;
    while(pslow && pfast)
    {
        pslow = pslow->next;
        step ++;
        pfast = pfast->next ? pfast->next->next : pfast->next;
        if(pslow->value == pfast->value) return step;
    }
}
int SingleList::getCircleEntrance()
{
    SLNode* pfirstMeet = firstMeet(phead);
    
    //无环的情况
    if(!pfirstMeet) return -1;
    SLNode* p1 = phead->next;
    SLNode* p2 = pfirstMeet;
    while(p1 != p2)
    {
        p1 = p1->next;
        p2 = p2->next;
    }
    return p1->value;
}
int main()
{
    SingleList* list = new SingleList();
    
    SLNode* p1 = new SLNode(1);
    SLNode* p3 = new SLNode(3);
    SLNode* p5 = new SLNode(5);
    SLNode* p7 = new SLNode(7);
    SLNode* p2 = new SLNode(2);
    SLNode* p4 = new SLNode(4);
    p1->next = p3;
    p3->next = p5;
    p5->next = p7;
    p7->next = p2;
    p2->next = p4;
    p4->next = p5;
    list->phead->next = p1;
    
    if(list->isCircle()){
        cout << "存在环,且长度为: " << list->getCircleLenth() <<  endl; 
        cout << "环的入口为: " << list->getCircleEntrance(); 
    }else{
        cout << "不存在环" ; 
    }
    return 0;
}输出:
![[数据结构] 单链表如何判环以及求环的长度,入口_数据结构_03](https://file.cfanz.cn/uploads/png/2022/06/14/3/7bT42b92Sa.png)
                










