判断两个链表是否相交

 微软亚院之编程----判断两个链表是否相交

给出两个单向链表的头指针,比如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;
}
原文地址:https://www.cnblogs.com/muzijie/p/5664518.html