您的位置:首页 > 其它

判断链表是否带环?若带环求环的长度?若带环求环的入口点?

2017-07-17 11:36 423 查看
链表就跟他的名字一样,是一串串起来的链,具体是什么样子在程序中是不能直观的看到的,因为每个节点的地址并不是连续的,但是我们可以通过指针,将其进行遍历访问。

今天我们来讨论一下,一个链表是否带环?若带环,那么环的长度又是多少?环的入口?

一个链表是否带环?

第一次拿到这道题的时候,我的函数原型是这样的

bool isCircle(ListNodeT* head)


判断一个链表是否带环,返回值最直接的应该就是bool,在C++中bool即真假判断。

第二版

ListNodeT* isCircle(ListNodeT* head)


因为如果带环的话,后面可能还要进行相应的使用,所以我想到了ListNodeT*作为返回值,这样可以得到是否带环的判断结果,又可以拿到带环的节点

网上有一种用到了pair

pair<Node<int>*, bool> isCircle(ListNodeT* head)


pair使用的原则,应该是上面两者的综合吧。

设置节点

template<class T>
struct ListNode
{
T _data;
ListNode<T>* _next;
ListNode(T x = T())
:_data(x)
, _next(NULL)
{}
};


为了统一,做typedef

typedef ListNode<int> ListNodeT;


判断是否带环

ListNodeT* isCircle(ListNodeT* head)
{
if (head == NULL)
{
printf("is no node in this list\n");
return NULL;
}
ListNodeT* first = head;
ListNodeT* second = head;
if (head->_next == NULL)
{
printf("List isn't have circle\n");
return NULL;
}
while (first->_next)
{
first = first->_next;
second = second->_next->_next;
if (first == second)
{
printf("List hava a circle\n");
return first;
}
}
printf("List isn't have circle\n");
return NULL;
}


通过快慢指针法,判断是否带环,好比跑步,假设两个人在跑步,且速度不变,一个快,一个慢,则在一定时间后,两个人肯定会再次相遇。

求带环环的长度

int length(ListNodeT* head,ListNodeT* node)
{
ListNodeT* cur = node->_next;
int count = 1;
while (cur != node)
{
count++;
cur = cur->_next;
}
return count;
}


判断带环函数返回的节点肯定是在换中的,当一个节点一直走,相遇的节点不动是,再次相遇,就可以求得环的长度

求环的入口

ListNodeT* FindLoopPort(ListNodeT*head, ListNodeT* node)
{
ListNodeT* cur = head;
while (cur != node)
{
cur = cur->_next;
node = node->_next;
}
return cur;
}


这里是一个数学公式的实践,交点node到入口点的距离=头指针到连接点的距离,因此,分别从交点、头指针开始走,相遇的那个点就是连接

假设链表总长为L,头节点到入口点的距离为a,入口点到快慢指针交点距离为x,环的长度为R,现在假设慢指针走了S步与快指针相遇,

s = a + x;

那么快指针走了2S步,

2s = a + nr + x;

就可以得到:a + x = nr;

->a = nr - x;

可以看出来,头节点到入口点的距离等于,交点到入口点的距离,那我们让两个指针,一个从交点走,一个从头节点走,最后一定在入口点相遇。

测试

int main()
{
ListNodeT* head = new ListNodeT(1);
ListNodeT* node1 = new ListNodeT(2);
ListNodeT* node2 = new ListNodeT(3);
head->_next = node1;
node1->_next = node2;
node2->_next = head;
ListNodeT* ret = NULL;
ret = isCircle(head);
if (ret !=NULL)
cout << length(head,ret) << endl;
if (ret != NULL)
cout << FindLoopPort(head, ret) << endl;
ListNodeT* node = FindLoopPort(head, ret);
cout << node->_data << endl;
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐