美文网首页
37 两个链表的第一个公共结点

37 两个链表的第一个公共结点

作者: WalkZeRo | 来源:发表于2016-06-28 22:26 被阅读0次

    分析

    注意观察有公共结点的两个链表有哪些特点
    有公共结点的两个单向链表,看起来像Y,而非X。从两个链表的尾部开始比较,最后一个相同的结点就是我们要找的点。
    可问题是在单向链表中,我们只能从头结点开始顺序遍历,最后到达的尾结点却要先被比较。这听起来像“后进先出”,于是我们想到使用<b>栈</b>结构。
    之所以需要用到栈,是因为我们想同时遍历到达两个栈的尾结点。当两个链表的长度不同时,如果我们从开头开始遍历到达尾结点的时间就不同。解决方法:第一步,先遍历两个链表,得到各自的长度。第二步,让长链表先走若干步,然后在同时在两个链表上遍历。

    #include <stdio.h>
    #include "list.h"
    
    unsigned int GetListLength(ListNode* pHead)
    {
        unsigned int nLength = 0;
        ListNode* pNode = pHead;
        while(pNode != NULL)
        {
            ++nLength;
            pNode = pNode->m_pNext;
        }
    
        return nLength;
    }
    
    ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2)
    {
        // 得到两个链表的长度
        unsigned int nLength1 = GetListLength(pHead1);
        unsigned int nLength2 = GetListLength(pHead2);
        int nLengthDif = nLength1 - nLength2;
    
        ListNode* pListHeadLong = pHead1;
        ListNode* pListHeadShort = pHead2;
        if(nLength2 > nLength1)
        {
            pListHeadLong = pHead2;
            pListHeadShort = pHead1;
            nLengthDif = nLength2 - nLength1;
        }
    
        //长链表先走nLengthDif步,再同时在两个链表上遍历
        for (int i = 0; i < nLengthDif; ++i)
        {
            pListHeadLong = pListHeadLong->m_pNext;
        }
    
        while((pListHeadLong != NULL) && 
            (pListHeadShort != NULL) && 
            (pListHeadLong != pListHeadShort))
        {
            pListHeadLong = pListHeadLong->m_pNext;
            pListHeadShort = pListHeadShort->m_pNext;
        }
    
        //得到第一个公共结点
        ListNode* pFirstCommonNode = pListHeadLong;
    
        return pFirstCommonNode;
    }
    
    // ====================测试代码====================
    void DestroyNode(ListNode* pNode);
    
    void Test(char* testName, ListNode* pHead1, ListNode* pHead2, ListNode* pExpected)
    {
        if(testName != NULL)
            printf("===%s begins: ===", testName);
    
        ListNode* pResult = FindFirstCommonNode(pHead1, pHead2);
        if(pResult == pExpected)
            printf("Passed.\n");
        else
            printf("Failed.\n");
    }
    
    // 第一个公共结点在链表中间
    // 1 - 2 - 3 \
    //            6 - 7
    //     4 - 5 /
    void Test1()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
        ListNode* pNode6 = CreateListNode(6);
        ListNode* pNode7 = CreateListNode(7);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode6);
        ConnectListNodes(pNode4, pNode5);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);
    
        Test("Test1", pNode1, pNode4, pNode6);
    
        DestroyNode(pNode1);
        DestroyNode(pNode2);
        DestroyNode(pNode3);
        DestroyNode(pNode4);
        DestroyNode(pNode5);
        DestroyNode(pNode6);
        DestroyNode(pNode7);
    }
    
    // 没有公共结点
    // 1 - 2 - 3 - 4
    //            
    // 5 - 6 - 7
    void Test2()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
        ListNode* pNode6 = CreateListNode(6);
        ListNode* pNode7 = CreateListNode(7);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);
    
        Test("Test2", pNode1, pNode5, NULL);
    
        DestroyList(pNode1);
        DestroyList(pNode5);
    }
    
    // 公共结点是最后一个结点
    // 1 - 2 - 3 - 4 \
    //                7
    //         5 - 6 /
    void Test3()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
        ListNode* pNode6 = CreateListNode(6);
        ListNode* pNode7 = CreateListNode(7);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode7);
        ConnectListNodes(pNode5, pNode6);
        ConnectListNodes(pNode6, pNode7);
    
        Test("Test3", pNode1, pNode5, pNode7);
    
        DestroyNode(pNode1);
        DestroyNode(pNode2);
        DestroyNode(pNode3);
        DestroyNode(pNode4);
        DestroyNode(pNode5);
        DestroyNode(pNode6);
        DestroyNode(pNode7);
    }
    
    // 公共结点是第一个结点
    // 1 - 2 - 3 - 4 - 5
    // 两个链表完全重合   
    void Test4()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
    
        Test("Test4", pNode1, pNode1, pNode1);
    
        DestroyList(pNode1);
    }
    
    // 输入的两个链表有一个空链表
    void Test5()
    {
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
    
        Test("Test5", NULL, pNode1, NULL);
    
        DestroyList(pNode1);
    }
    
    // 输入的两个链表都是空链表
    void Test6()
    {
        Test("Test6", NULL, NULL, NULL);
    }
    
    void DestroyNode(ListNode* pNode)
    {
        delete pNode;
        pNode = NULL;
    }
    
    int main(void)
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
    
        return 0;
    }
    

    结果

    QQ截图20160628222040.jpg

    相关文章

      网友评论

          本文标题:37 两个链表的第一个公共结点

          本文链接:https://www.haomeiwen.com/subject/ftuzdttx.html