1. 判断单链表是否带环?若带环,求环的长度?求环的入口点?
//判断是否带环
ListNode* IsCycle(ListNode* list)
{
ListNode* fast = list, *slow = list;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)
{
return NULL;
}
}
}
//求环的长度
int GetCycleLen(ListNode* list, ListNode* meetNode)
{
if (NULL == list || meetNode == NULL)
{
return 0;
}
int count = 1;
ListNode* cur = meetNode;
while (cur->next != meetNode)
{
count++;
cur = cur->next;
}
return count;
}
//求环的入口点
ListNode* GetcycleEntry(ListNode* list, ListNode* meetNode)
{
if (NULL == list || meetNode == NULL)
{
return 0;
}
while (1)
{
if (list == meetNode)
{
return list;
}
list = list->next;
meetNode = meetNode->next;
}
return meetNode;
}
2. 判断两个链表是否相交,若相交,求交点。(假设链表不带环)
两个链表相交有公共的链存在,即有相同的尾就相交。
//判断两个链表是否相交
bool CheckIsMeet(ListNode* list1, ListNode* list2)
{
if (list1 == NULL || list2 == NULL)
{
return false;
}
ListNode* tail1 = list1;
ListNode* tail2 = list2;
while (tail1->next)
{
tail1 = tail1->next;
}
while (tail2->next)
{
tail2 = tail2->next;
}
if (tail1 == tail2)
{
return true;
}
else
{
return false;
}
}
//求交点
ListNode* GetMeetNode(ListNode* list1, ListNode* list2)
{
ListNode* cur1 = list1;
ListNode* cur2 = list2;
int len1 = 0, len2 = 0;
while (cur1)
{
len1++;
cur1 = cur1->next;
}
while (cur2)
{
len2++;
cur2 = cur2->next;
}
ListNode* longList = list1, *shortList = list2;
if (len1 < len2)
{
longList = list2;
shortList = list1;
}
int gap = abs(len1 - len2);
while (gap--)
{
longList = longList->next;
}
while (longList)
{
if (longList == shortList)
{
return longList;
}
longList = longList->next;
shortList = shortList->next;
}
return NULL;
}
3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
1)L1 和 L2 都不带环,求链表的尾判断是否带环,及求交点。
2)L1 带环,L2 不带环;或 L1 不带环,L2 带环,不相交。
3)L1 和 L2 都带环,分三种情况:
(1)入口点在环外----交点+入口点
(2)入口点在环内----两个点既是交点,也是入口点。
(3)不相交。
ListNode *IntersectRing(ListNode *list, ListNode *plist)
//判断两个链表是否相交,若相交,求交点。
{
ListNode* oep1 = OepRing(list);
ListNode* oep2 = OepRing(plist);
//两个链表都不带环
if ((oep1 == NULL) && (oep2 == NULL))
{
return Intersect(list, plist);
}
//一个带环,一个不带环(不相交)
else if (((oep1 == NULL) && oep2) || ((oep2 == NULL) && oep1))
{
return NULL;
}
//两个都带环
else
{
//尾交(一个交点,一个入口点)
//若两个链表的入口点一样则只有一个交点(交点也是入口点)
//两链表各自环入口点已经求出,把list的环从入口点断开
//可以转换成求不带环的相交链表求交点
if (oep1 == oep2)
{
oep1->next = NULL;
return Intersect(list, plist);
}
else
{
//环交
//环交会有两个入口点,从一个入口点出发遍历环
//遍历的过程中有结点等于另一个入口点,则表示环交,返回指向那个结点的指针(就是交点)
//有两个交点,交点也是入口点。
//否则,就是两个带环链表不相交
//在这里返回的是第二个链表的入口点
//也是第一个链表在第二个链表中的交点
ListNode* cur = oep1->next;
while (cur != oep1)
{
if (cur == oep2)
{
return oep1;
}
cur = cur->next;
}
/*//在这里返回的是第一个链表的入口点
//也是第二个链表在第一个链表中的交点
ListNode* cur = oep2->next;
while (cur != oep2)
{
if (cur == oep1)
{
return oep2;
}
cur = cur->next;
}*/
return NULL; //不相交
}
}
}
4.复杂链表的复制。一个链表的每个节点,有一个指向 next 指针指向下一个节点,还有一个 random 指针指向这个链表中的一个随机节点或者 NULL,现在要求实现复制这个链表,返回复制后的新链表。
void NewBackPrime(ComplexNode *list)
//把新创建的每个结点链接到原先结点的后面
{
ComplexNode *cur = list;
while (cur)
{
//每次新创建一个结点,让它指向原先结点指向的结点
//新创建结点的data和原先结点一样
ComplexNode *head = Init(cur->_data);
head->_next = cur->_next;
//新创建结点的指向的随机结点置空
head->_random = NULL;
//原先结点指向新创建的结点,这样整个链表就连到了一块
cur->_next = head;
//cur依次后移
cur = head->_next;
}
}
void ComplexNodeRandom(ComplexNode *list)
//复制随机结点
{
ComplexNode *cur = list;
while (cur)
{
//找到插入的新结点
ComplexNode *head = cur->_next;
//让新结点指向的随机结点
//去指向
//原先结点指向随机结点的后一个
if (cur->_random)
{
head->_random = cur->_random->_next;
}
cur = head->_next;
}
}
ComplexNode *RemoveNewCode(ComplexNode *list)
//让新创建链表的结点链接起来,原先链表的结点链接起来
{
ComplexNode *cur = list;
ComplexNode *head = NULL;
ComplexNode *tmp = NULL;
if (cur)
{
head = tmp = cur->_next;
cur->_next = tmp->_next;
cur = cur->_next;
}
while (cur)
{
//让新创建链表的结点链接起来
tmp->_next = cur->_next;
tmp = tmp->_next;
//原先链表的结点链接起来
cur->_next = tmp->_next;
cur = cur->_next;
}
return head;
}
ComplexNode *ComplexList(ComplexNode *list)
//复杂链表的复制
{
NewBackPrime(list);
ComplexNodeRandom(list);
return RemoveNewCode(list);
}