zoukankan      html  css  js  c++  java
  • 判断两个链表是否相交

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

    给出两个单向链表的头指针,比如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;
    }
  • 相关阅读:
    BZOJ 3506 机械排序臂 splay
    BZOJ 2843 LCT
    BZOJ 3669 魔法森林
    BZOJ 2049 LCT
    BZOJ 3223 文艺平衡树 splay
    BZOJ 1433 假期的宿舍 二分图匹配
    BZOJ 1051 受欢迎的牛 强连通块
    BZOJ 1503 郁闷的出纳员 treap
    BZOJ 1096 ZJOI2007 仓库设计 斜率优化dp
    BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
  • 原文地址:https://www.cnblogs.com/muzijie/p/5664518.html
Copyright © 2011-2022 走看看