一、判断两个链表是否相交
int CheckCross(pLinkList list1, pLinkList list2) //判断链表是否相交
{
assert(list1);
assert(list2);
pLinkNode cur1 = list1->pHead;
pLinkNode cur2 = list2->pHead;
if ((NULL==list1->pHead)||(NULL==list2->pHead))
{
return -1;
}
while (NULL!=cur1->next)
{
cur1 = cur1->next;
}
while(NULL!=cur2->next)
{
cur2 = cur2->next;
}
if (cur1 == cur2)
{
return 1; //相交
}
else
{
return -1; //不相交
}
}
二、合并两个有序链表
合并两个有序链表的方法很多,下面介绍一种最常见的方法!!!
算法:
首先创建一个虚拟头结点,将两个链表看做两个有序集合,每次从这两个集合里面分别取出第一个结点进行比较,把较小值从集合中剥离出来链接到虚拟结点之后,再用一个指针last记录虚拟结点这条链表的末尾,如此反复进行,直到其中一个集合为空,再将另一个集合中的所有结点链接到last之后。
pLinkList Merge(pLinkList list1, pLinkList list2) //合并两个有序链表
{
assert(list1);
assert(list2);
if ((NULL == list1->pHead)&&(NULL == list2->pHead)) //考虑特殊情况
{
return NULL;
}
else if (NULL == list1->pHead)
{
return list2;
}
else if(NULL == list2->pHead)
{
return list1;
}
pLinkNode last = NULL;
pLinkNode newHead = NULL; //虚拟头结点
if (list1->pHead->data <list2->pHead->data) //把对第一个结点特殊处理
{
newHead= list1->pHead;
list1->pHead = list1->pHead->next;
}
else
{
newHead = list2->pHead;
list2->pHead = list2->pHead->next;
}
last=newHead; //让last指向虚拟结点链表的尾部
while ((NULL!= list1->pHead)&&(NULL!= list2->pHead))
{
if (list1->pHead->data <list2->pHead->data)
{
last->next = list1->pHead;
list1->pHead = list1->pHead->next;
}
else
{
last ->next= list2->pHead;
list2->pHead = list2->pHead->next;
}
last = last->next;
}
if (NULL == list1->pHead) //将集合中剩下的元素链接到last之后
{
last->next = list2->pHead;
}
else
{
last->next = list1->pHead;
}
list1->pHead = newHead;
return list1;
}
三、判断一个链表是否带环,若带环返回相遇点的位置
这个问题需要应用到快慢指针才能解决,快指针fast每次走两步,慢指针每次走一步。因为fast每次都要比slow多走一步,如果链表带环,则最终fast一定会和slow相遇。
pLinkNode CheckCycle(pLinkList list) //判断是否带环,若带环则返回相遇位置
{
assert(list);
pLinkNode fast = list->pHead; //快指针
pLinkNode slow = list->pHead; //慢指针
if (NULL==list->pHead)
{
return NULL;
}
while (fast!= NULL)
{
if (NULL != fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
else
{
break;
}
if (fast == slow) //快慢指针相遇则有环
{
return slow;
}
}
return NULL; //没环则返回NULL
}
四、求带环链表中环的长度
这个问题比较简单,第三题中已经找到了快慢指针在环中的相遇点,我们只需要再设置一个count,从这个相遇点出发遍历一遍环就行了。
int GetCircleLength(pLinkNode meet) //若链表带环这返回环的长度
{
assert(meet);
pLinkNode cur = meet->next;
int count = 1;
while (cur!=meet)
{
count++;
cur = cur->next;
}
return count;
}
五、求带环链表中环的入口点
针对这个问题我们有一个定理,用两个指针,分别从链表的头和环中的相遇点出发,经过若干步之后这两个指针会在环的入口处相遇。
pLinkNode GetCycleEntryNode(pLinkList list, pLinkNode meet) //查找环的入口
{
assert(list);
pLinkNode link = list->pHead; //link指向链表的头
pLinkNode cycle = meet; //cycle指向链表的相遇点
while (link != cycle)
{
link = link->next;
cycle = cycle->next;
}
return link;
}