[数据结构] 单链表如何判环以及求环的长度,入口

目录

如何判环?

如何求环的长度?

如何求环的入口呢?

示例


如何判环?

思路: 利用两个移动速度不同的指针,若在均不为空的情况下相遇,则存在环

如何求环的长度?

思路:若存在环,那么快慢指针从相遇点重新出发到再次相遇的过程中, 一定是慢指针走了一圈,快指针走了两圈, 慢指针所走过的步数即为环的长度

如何求环的入口呢?

推理:

 所以,我们在相遇点位和链表的起点分别设立两个速度相同的指针,当他们相遇时即在环的入口

示例

其中测试数据的关系如图

#include<iostream>
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;
}

输出:

本文来自博客园,作者:泥烟,CSDN同名, 转载请注明原文链接:https://www.cnblogs.com/Knight02/p/15799006.html

原文地址:https://www.cnblogs.com/Knight02/p/15799006.html