判断两个链表是否相交
微软亚院之编程----判断两个链表是否相交
给出两个单向链表的头指针,比如h1,h2,判断这两个链表是否相交。
分析:
(1)先判断链表有无环,如果一个有环,一个没有环,则说明两个链表肯定不会相交。
(2)如果两个链表都没有环,则如果两个链表相交,两个链表的最后一个结点肯定是同一个结点。
(3)如果两个链表h1,h2都有环,则可以找到两个链表上并且在环上的任何一个结点p1和p2。如果从结点p1开始遍历链表h1,能够遍历到p2,说明两个链表相交;否则从p1开始遍历h1,遍历一圈后又回到p1,而未遍历到p2,说明两个链表不相交。
(4)检查单链表是否有环的方法:
使用两个指针p1,p2 从链表头开始遍历,p1 每次前进一步,p2 每次前进两步。如果p2 到达链表尾部,说明无环,否则p1、p2 必然会在某个时刻相遇(p1==p2),从而检测到链表中有环。
#include <stdio.h> #include <stdlib.h> typedef int ElemType; //定义链表的存储结构 typedef struct Node { ElemType data; struct Node *next; } Node; typedef struct Node *LinkList; typedef struct Node *pNode; //判断两个链表是否相交 int isListJoined(pNode p1, pNode p2); //判断单链表有无环,如果有环,返回环上的任意结点,否则返回NULL pNode testCycle(LinkList L); //假设两个单链表都没有环 int isJoinedSimple(pNode h1, pNode h2); //创建单链表(n表示链表长度,isCycle表示是否有环) LinkList createLinkList(int n, int isCycle); //判断两个链表是否相交 int isListJoined(pNode p1, pNode p2) { pNode cycle1 = testCycle(p1); pNode cycle2 = testCycle(p2); if ((cycle1 != NULL && cycle2 == NULL) || (cycle1 == NULL && cycle2 != NULL)) { //如果一个有环,一个没有环 return 0; } if (cycle1 == NULL && cycle2 == NULL) { //两个都没有环 return isJoinedSimple(p1, p2); } //两个都有环 pNode p = cycle1; while (1) { if (p == cycle2 || p->next == cycle2) { return 1; } p = p->next->next; cycle1 = cycle1->next; if (p == cycle1) { return 0; } } } //判断单链表有无环,如果有环,返回环上的任意结点,否则返回NULL pNode testCycle(LinkList L) { pNode p1 = L; pNode p2 = L; while (p2 != NULL && p2->next != NULL) { p1 = p1->next; p2 = p2->next->next; if (p1 == p2) { return p1; } } return NULL; } //假设两个单链表都没有环 int isJoinedSimple(pNode h1, pNode h2) { while (h1->next) { h1 = h1->next; } while (h2->next) { h2 = h2->next; } if (h1 == h2) { return 1; } return 0; } //创建单链表 LinkList createLinkList(int n, int isCycle) { LinkList L = NULL; pNode p, r = NULL; ElemType e; for (int i = 0; i < n; i++) { printf("请输入第%d个数字", i + 1); scanf("%d", &e); p = (pNode)malloc(sizeof(Node)); if (p == NULL) { printf("out of space"); exit(1); } p->data = e; if (i == n-1 && isCycle == 1) { p->next = L; //此处是让链表的尾结点的next指针指向头结点 } else { p->next = NULL; } if (L == NULL) { L = p; } else { r->next = p; } r = p; } return L; } int main(int argc, const char * argv[]) { //创建两个没有环的链表,并且不相交 LinkList h1 = createLinkList(10, 0); LinkList h2 = createLinkList(5, 0); int isJoined1 = isListJoined(h1, h2); printf("%d", isJoined1); //创建两个没有环的链表,并且相交 LinkList h3 = createLinkList(5, 0); LinkList h4 = h3; int isJoined2 = isListJoined(h3, h4); printf("%d", isJoined2); //创建两个有环的链表,并且不相交 LinkList h5 = createLinkList(5, 1); LinkList h6 = createLinkList(4, 1); int isJoined3 = isListJoined(h5, h6); printf("%d", isJoined3); //创建两个有环的链表,并且相交 LinkList h7 = createLinkList(5, 1); LinkList h8 = h7; int isJoined4 = isListJoined(h7, h8); printf("%d", isJoined4); return 0; }