一、判断两个链表是否相交
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; }
时间: 2024-10-09 04:55:46