1、复杂链表的复制
复杂链表
一个链表的每个结点,有一个next指针指向下一个结点,还有一个random指针指向这个链表中的随机一个结点或者NULL。
现在要求复制这个链表,并返回复制后的新链表。
思路如下:
复杂链表的数据类型:
typedef struct ComplexNode
{
int data;
ComplexNode *next;
ComplexNode *random;
}ComplexNode;
代码如下:
//创建一个新结点
ComplexNode *CreateComNode(int data)
{
ComplexNode *newNode = (ComplexNode *)malloc(sizeof(ComplexNode));
newNode->data = data;
newNode->next = NULL;
newNode->random = NULL;
return newNode;
}
ComplexNode *CopyComplexList(ComplexNode **pFirst)
{
ComplexNode *newNode = NULL;
ComplexNode *cur = NULL;
//1.复制每个结点,让新结点跟在老结点后面
cur = *pFirst;
while(cur != NULL)
{
newNode = CreateComNode(cur->data);
newNode->next = cur->next;
cur->next = newNode;
cur = newNode->next;
}
//2、复制random
cur = *pFirst;
while(cur != NULL)
{
newNode = cur->next;
if(cur->random != NULL)
{
newNode->random = cur->random->next;
}
cur = newNode->next;
}
//3、把一个链表拆成两个链表
ComplexNode *newNext = NULL;
ComplexNode *next = NULL;
ComplexNode *result = NULL;
int flag = 1;
cur = *pFirst;
while(cur != NULL)
{
newNode = cur->next;
if(flag)
{
result = newNode;
flag = 0;
}
next = newNode->next;
if(next == NULL)
{
newNext = NULL;
}
else
{
newNext = next->next;
}
cur->next = next;
newNode->next = newNext;
cur = next;
}
return result;
}
2、判断两个链表是否相交,若相交,求交点(假设链表不带环)
思路如下:
代码如下:
//计算链表长度
int GetListLen(ListNode *p)
{
int count = 0;
ListNode *cur = p;
while(cur != NULL)
{
count++;
cur = cur->next;
}
return count;
}
//判断两条链表是否相交,若相交,返回交点
ListNode *IsIntersect(ListNode *p1, ListNode *p2)
{
ListNode *cur1 = p1;
ListNode *cur2 = p2;
int len1 = 0;
int len2 = 0;
int ret = 0;
while(cur1 != NULL)
{
cur1 = cur1->next;
}
while(cur2 = cur2->next)
{
cur2 = cur2->next;
}
if(cur1 == cur2)//如果条件成立,说明相交
{
cur1 = p1;
cur2 = p2;
len1 = GetListLen(p1);
len2 = GetListLen(p2);
if(len1>len2)
{
ret = len1-len2;
while(ret--)
{
cur1 = cur1->next;
}
}
else if(len1<len2)
{
ret = len2-len1;
while(ret--)
{
cur2 = cur2->next;
}
}
while(cur1 != cur2)
{
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1; //找到交点
}
else
return NULL;
}
3、判断单链表是否带环?若带环,求环的长度?求环的入口点?
思路如下:
代码如下:
//判断是否带环,带环返回快慢指针相遇结点
ListNode *IsCircleList(ListNode *p)
{
int count = 0;
ListNode *fast = p;
ListNode *slow = p;
while(fast != NULL)
{
fast = fast->next;
count++;
if(count%2==0)
{
slow = slow->next;
}
if(fast == NULL)
{
break;
}
if(fast == slow)
{
return fast;
}
}
return NULL;
}
//求环的长度
int LenOfCircle(ListNode *p)
{
int count = 0;
ListNode *cur = NULL;
ListNode *NodeInCircle = NULL;
//从头遍历链表,找到相遇点
NodeInCircle = IsCircleList(p);
cur = p;
while(cur != NodeInCircle)
{
cur = cur->next;
}
while(cur->next != NodeInCircle)
{
cur = cur->next;
count++;
}
count++;
return count;
}
//求环的入口点
ListNode *EntryNode(ListNode *p)
{
ListNode *dot = NULL;
ListNode *ret = NULL;
ListNode *cur = NULL;
ListNode *NodeInCircle = NULL;
//从头遍历链表,找到相遇点
NodeInCircle = IsCircleList(p);
cur = p;
//找出相遇点的前一个结点,将它置为空指针,相当于从相遇点断开环
//然后以两条链表相交的角度找入口点,两条链表相交处就是环的入口点
while(cur->next != NodeInCircle)
{
cur = cur->next;
}
dot = cur;
cur->next = NULL;
cur = NodeInCircle;
ret = p;
while(cur != ret)
{
cur = cur->next;
ret = ret->next;
}
dot->next = NodeInCircle;
return cur;
}
4、判断两个链表是否相交,若相交,求交点(假设链表带环)【升级版】
思路如下: