17_7_16:判断两个链表是否相交,若相交,求交点。如果链表带环呢?

来源:互联网 发布:windows系统管理书籍 编辑:程序博客网 时间:2024/05/14 08:59

1.【基础题】–1.判断两个链表是否相交,若相交,求交点。(假设链表不带环)2.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】

2.【附加题】–请问下面的程序一共输出多少个“-”?

#include <stdio.h>#include <unistd.h>int main(void) { int i; for(i=0; i<2; i++){ fork(); printf("-"); } return 0; }

**

基础题:

**
定义的单链表节点

#include <iostream> //采用C++编译环境。typedef struct ListNode{    int _val;    ListNode* _pNext;}Node, *PNode;

在代码中定义的一些函数

//获取环中节点中快慢指针的碰撞点。PNode Get_Impact_Point(PNode pHead);//获取带环链表中环的入口点PNode Get_Entrance_Point(PNode pHead);//判断两个链表是否相交,若相交,求交点。(假设链表不带环)PNode Is_Has_Intersection(PNode pHead_1, PNode pHead_2);//判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】PNode Is_Has_Intersection_2(PNode pHead_1, PNode pHead_2);

1.判断两个链表是否相交,若相交,求交点。(假设链表不带环)

思路:
不带环的两个链表相交,表示从交节点开始,两个链表中的节点一直相同。
那么两个链表的最后一个节点也相同。可以当做一个判断条件。
如果两个不带环链表相交,则将其中一个链表的头尾节点相连,构成一个带环的单链表。
这样问题就变为了,求带环单链表的环的入口点的问题。这里写图片描述

PNode Is_Has_Intersection(PNode pHead_1, PNode pHead_2){    if ((NULL == pHead_1) || (NULL == pHead_2)) //当有空链表时,没有交点。        return NULL;    if (pHead_1 == pHead_2) //如果两个链表是通过一个链表的情况。        return pHead_1;    PNode pTail_1 = pHead_1;  //用来指向pHead_1的尾节点    PNode pTail_2 = pHead_2;  //用来指向pHead_2的尾节点    while (pTail_1->_pNext)           pTail_1 = pTail_1->_pNext;      while (pTail_2->_pNext)        pTail_2 = pTail_2->_pNext;    if (pTail_1 != pTail_2)  //两个链表最后一个节点不相等,说明没有相交。        return NULL;      //走到这里,说明pTail_1 = pTail_2。两个链表相交,下面开始求交点。    //将其中一个链表的头结点与尾节点相连。最终两个链表会构成一带环单链表    //问题变为求带环单链表的环的入口了。    //1,将两个单链表变为带环单链表(pHead_2为新的头指针)    pTail_1->_pNext = pHead_1;    //2,求环的入口。(调用写的函数,前一篇博文已写,后面也会给出)    PNode pCross = Get_Entrance_Point(pHead_2);    return pCross;}

2.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
思路:
先判断两个链表是否是同一个链表的情况。
1,相同,直接返回头结点。
2,不相同,在往下走。
再判断两个链表是否带环。
1,都不带环—>判断两个不带环单链表是否相交,若相交,求交点。
2,一个带环,一个不带环—->不想交
3,两个链表都带环—->1,交点在环外,2,交点再环内,3,不相交
通过两个链表环的入口点是否相等,来判断交点在环外还是环内。
若相等,则在环外或者就是入口点处。此时相交。–》去掉环,变为求两个不带环单链表求交点交点
若不相等,则判断两个入口点是否在通过一个环中,若在环中,则两个入口点都是交点。否则,不相交。
这里写图片描述

PNode Is_Has_Intersection_2(PNode pHead_1, PNode pHead_2){    //存在空链表,不存在交点    if ((NULL == pHead_1) || (NULL == pHead_2))        return NULL;    //如果两个链表是同一个链表,则直接返回头结点。    if (pHead_1 == pHead_2)        return pHead_1;    PNode pCross = NULL; //交点    //获取链表快慢指针的碰撞点,如果存在,则说明链表有环    PNode pImpact_1 = Get_Impact_Point(pHead_1);    PNode pImpact_2 = Get_Impact_Point(pHead_2);    //都不带环--->判断两个不带环单链表是否相交,若相交,求交点。    if ((NULL == pImpact_1) && (NULL == pImpact_2))    {        pCross = Is_Has_Intersection(pHead_1, pHead_2);        return pCross;    }    //一个带环,一个不带环---->不相交    if (!pImpact_1 || !pImpact_2)         return NULL;    //两个链表都带环---->若相交,环是公有的,则判断链表1的碰撞点是否在链表2的环中    //两个链表都带环的情况。    //有三种情况。    //1,不相交。    //2,相交,交点在环外。    //3,相交,交点在环内。    //为了不重复定义变量,浪费空间,暂时用pImpact指向返回的环入口点。    pImpact_1 = Get_Entrance_Point(pHead_1);    pImpact_2 = Get_Entrance_Point(pHead_2);    //此时,带环链表有可能相交于环内,有可能不相交    if (pImpact_1 != pImpact_2)    {        PNode pCur = pImpact_2;   //作为遍历pHead_2的指针         //需要注意的是,在遍历pHead_2时,如果pHead_1的入口点不在pHead_2的环中,会死循环        //所以,需要从pHead_2的环入口点,开始遍历,直到再次遇到入口点。        while (pCur != pImpact_1)        {            pCur = pCur->_pNext;            if (pCur == pImpact_2) //防止在环内一直遍历,而死循环                break;        }        //pHead_1的入口点pImpact_1在pHead_2的环中,即相交,随便返回一个入口点        if (pCur == pImpact_1)        {            return pImpact_1;        }        else  //否则,不相交        {            return NULL;        }    }    //pImpact_1 == pImpact_2    //此时,两个链表有一个公共环,并且,节点在环外。--》去掉环的影响,变为求两个不带环单链表求交点问题    PNode pTemp = pImpact_1->_pNext; //记录,环的入口的下一节点。    pImpact_1->_pNext = pHead_1; //去掉旧环,构成一个新环(pHead_2为头结点)    //获取新环的入口点,即原来两个链表的交点    pCross = Get_Entrance_Point(pHead_2);    //去掉新环,还原旧环    pImpact_1->_pNext = pTemp;     return pCross;}

3.下面给出上述两个函数中调用的自定义函数

//获取环中节点中快慢指针的碰撞点。PNode Get_Impact_Point(PNode pHead){    if (NULL == pHead)        return NULL;    PNode pFast = pHead; //快指针每次走两步    PNode pSlow = pHead; //慢指针每次走一步    while ((NULL != pFast) && (NULL != pFast->_pNext))    {        pFast = pFast->_pNext->_pNext;        pSlow = pSlow->_pNext;        if (pFast == pSlow)            break;    }    if ((NULL == pFast) || (NULL == pFast->_pNext)) //不可使用pFast!=pSlow作为判断条件,当链表只有一个元素时,会出错。        return NULL;    return pFast;}
//获取带环链表中环的入口点PNode Get_Entrance_Point(PNode pHead){    PNode pImpact = Get_Impact_Point(pHead);    if (NULL == pImpact) //链表中不存在环        return NULL;     //头结点到入口点的长度设为:X    //环的长度设为R    //碰撞点到入口的长度设为:R1    //通过计算(前一篇博文中写有),可以推到出存在某一个n(n为非负整数),使得:X = nR + R1.    //所以,头结点和碰撞点同时出发, 最终会在入口点相遇。    while (pImpact != pHead)    {        pImpact = pImpact->_pNext;        pHead = pHead->_pNext;    }    //此时,两者都在入口点处,返回入口点位置。    return pImpact; }

**

附加题

**
关于fork函数的知识,推荐博文:http://blog.csdn.net/jason314/article/details/5640969
里面对于fork进行了深入的讲解。而且例子也比较好。也包括这个例子。
下面,呈现在ubuntu下运行的结果图。
li这里写图片描述
结果打印了6个‘-’
这里写图片描述

阅读全文
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 即时库存有负数怎么办 电脑软件被拦截怎么办 超市无条码商品怎么办 场外期权有诈骗怎么办 ip地址访问受限怎么办 电脑ip地址受限怎么办 百度云资源打不开怎么办 百度网盘看文件字太小怎么办 密码输入三次错误怎么办 notes邮箱满了怎么办 小米8买不到怎么办 小米付款不发货怎么办 小米金融还款中怎么办 股票遇到闪崩怎么办 微信插件没有怎么办 excel打印太小怎么办 工地临时人员死亡怎么办 哺乳期乳腺增生疼怎么办 哺乳期有乳腺增生怎么办 哺乳期得了乳腺增生怎么办 中等教育认证花名册丢失怎么办 哺乳期囊性结节怎么办 乳腺增生堵奶怎么办 月子期乳房增生怎么办 母乳期乳腺增生怎么办 上市公司破产了股票怎么办 iptv错误码30022怎么办 电信iptv不清晰怎么办 电信iptv卡顿怎么办 pr滚动字幕闪烁怎么办 电视车表盘看不清怎么办 图片字看不清楚怎么办 字太潦草看不清怎么办 微信图片看不清怎么办 小车上坡没动力怎么办 上海牌照拍到了怎么办 杭州车牌摇不到怎么办 孩子不上进家长怎么办 孩子读书蠢以后怎么办 上海银行储蓄卡怎么办 分数不够读高中怎么办