链表题--难点

原创 2017年09月26日 21:26:25
  1. 判断单链表是否带环?若带环,求环的长度?求环的入口点?
    判断是否带环:要判断链表有没有带环,不能按常理去判断最后一个节点的next是否为空,因为带环链表找不到最后一个节点。需借助快慢指针来解决。定义fast指针每次走两步,slow指针每次走一步,这样fast指针和slow指针如果在环里相遇,就可以断定有环,否则无环。
ListNode* Is_Loop_List(ListNode* pList)//是否带环,并返回相遇点
{
    if (pList == NULL)
    {
        return NULL;
    }
    ListNode* fast = pList;
    ListNode* slow = pList;
    while (fast->next && fast)
    {
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow)
        {
            return slow;
        }
    }
    return NULL;
}
这里就出现了新问题:fast指针可以一次走三步,走四步……吗???
答案肯定是不能。因为fast每次走两步,slow每次走一步,快慢指针每次缩小的距离是一步,不会出现错过或者跳过的情况。而如果fast指针一次走三步,四步,会出现跳过的情况。

求环的长度:根据快慢指针相遇点,从相遇点的next开始遍历,当遇到相遇点停止,count进行计数,count值即为环的长度。

int Length_Loop(ListNode* pList)//求环的长度
{
    ListNode* meethead = Is_Loop_List(pList);
    while (meethead)
    {
        ListNode* prev = meethead->next;
        int count = 1;
        while (prev != meethead)
        {
            count++;
            prev = prev->next;
        }
        return count;
    }
    return 0;
}

求环的入口点:

这里写图片描述
上图可知:从环头节点和相遇点遍历节点,会在某个节点处相遇,这个节点就是环入口点。

ListNode* Enter_Node(ListNode* pList)//求环的入口点
{
    ListNode* meethead = Is_Loop_List(pList);
    while (meethead)
    {

        while (pList != meethead)
        {
            pList = pList->next;
            meethead = meethead->next;
        }
        return pList;
    }
    return NULL;
}

2.判断两个不带环链表是否相交,若相交,求交点。
先举例看一下何为相交链表

这里写图片描述
1>,先分别求出两个链表的长度,求出长度差;
2>,让长链表先走长度差的距离,接着短链表和长链表一起走;
3>,当出现节点数值一样时,那么相交点就找到了。

int Check_cross(ListNode* pList1, ListNode* pList2)//是否相交
{
    if (pList1 == NULL || pList2 == NULL)
    {
        return 0;
    }
    ListNode* prev1 = pList1;
    ListNode* prev2 = pList2;
    while(prev1->next)
    {
        prev1 = prev1->next;
    }
    while ( prev2->next)
    {
        prev2 = prev2->next;
    }
    if (prev1->data == prev2->data)
    {
        return 1;
    }
    return 0;
}

int Length_List(ListNode* pList)//求链表长度
{
    if (pList == NULL)
    {
        return 0;
    }
    int count = 1;
    while (pList->next)
    {
        count++;
        pList = pList->next;
    }
    return count;
}

ListNode* List_Intersection(ListNode* pList1, ListNode* pList2)//求链表的交点
{
    int Len1 = Length_List(pList1);
    int Len2 = Length_List(pList2);
    ListNode* longlist = pList1;
    ListNode* shortlist = pList2;
    if (Len1 < Len2)
    {
        longlist = pList2;
        shortlist = pList1;
    }
    int tmp = abs(Len1-Len2);
    while (tmp--)
    {
        longlist = longlist->next;
    }
    while (longlist)
    {
        if (longlist->data == shortlist->data) 
        {
            return longlist;
        }
        shortlist = shortlist->next;
        longlist = longlist->next;
    }
    return NULL;
}

3,判断两个链表是否相交,若相交,求交点。(假设链表可能带环)
分为以下几种情况:

这里写图片描述

ListNode* List_loop_cross(ListNode* pList1, ListNode* pList2)
{
    if (pList1 == NULL || pList2 == NULL)
    {
        return NULL;
    }
    ListNode* enter1 = Enter_Node(pList1);//入口点
    ListNode* enter2 = Enter_Node(pList2);
    if (enter1 == NULL && enter2 == NULL)//两个链表的入口点为空,不带环 判断有无交点
    {
        return List_Intersection(pList1, pList2);
    }
    else if ((enter1 != NULL&&enter2 == NULL) || 
            (enter1 == NULL&&enter2 != NULL))//一个链表有环,一个链表无环,不相交
    {
        return NULL;
    }
    else if (enter1 == enter2)//入口点相等
    {
        enter1->next = NULL;
        enter2->next = NULL;//去掉环之后,按无环处理
        return List_Intersection(pList1, pList2);
    }
    else//一个环上有两个入口点
    {
        ListNode* cur = enter1->next;
        while (cur != enter1)
        {
            if (cur == enter2)
            {
                return cur;
            }
            cur = cur->next;
        }
        return NULL;
    }
}

4.求两个已排序单链表中相同的数据
1>,当两个节点数值相等时,尾插到新建链表上,并同时向后走一步;
2>,当两个数不相等时,数值小的节点向后走一步,数值大的节点不动,继续进行比较,直到任意链表为空。

ListNode* Union_Node(ListNode* List1, ListNode* List2)
{
    ListNode* newlist = NULL;
    ListNode* cur = List1;
    ListNode* prev = List2;
    while (cur && prev)
    {
        if (cur->data == prev->data)
        {
            PushBack(&newlist, cur->data);
            cur = cur->next;
            prev = prev->next;

        }
        else if (cur->data > prev->data)
        {
            prev = prev->next;
        }
        else
        {
            cur = cur->next;
        }
    }
    return newlist;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

Hibernate学习笔记:难点,常见面试题

无论多复杂,hibernate终究是一个和数据库打交道的框架,与jdbc功能一样。所以没有理由畏惧hibernate. hibernate的难点我觉得有两方面:一是性能优化,二是session管理。性...

水平分库分表的关键步骤和技术难点

目录(?)[-] 分片技术的由来分布式全局唯一ID 分片字段该如何选择常见分片规则数据迁移容量规划扩容等问题 跨分片技术问题 跨分片的排序分页跨分片的函数处理跨分片join全局表E...

表驱动法应用的难点

表驱动法就是两个过程: i. 提取共性,做到为每个元素做一样的事。把共性放到表中, 用查表法取代switch。 ii. 提供支持函数,因为提取共性后会要求有为这些共性服务的函数。第1步是比较简单的,把...

从Windows下Java程序如何操作Linux下Hbase数据库表过程、难点的心得历程

Java客户端访问Hbase 1.      过程 A. 首先搭建Hadoop集群、在集群中搭建zookeeper最后搭建Hbase(在搭建过程中由于最新版本不稳定建议采用较低版本的Hadoop:2....

视图中的难点:主键表 About Key-Preserved Tables

http://wmlm.itpub.net/post/12871/278640 因为在项目中大量地使用了视图,而在视图上的更新上产生了一点儿问题,所以抽时间对可更新视图进行了复习,英文看得多了,也就...

水平分库分表的关键步骤和技术难点

在之前的文章中,我介绍了分库分表的几种表现形式和玩法,也重点介绍了垂直分库所带来的问题和解决方法。本篇中,我们将继续聊聊水平分库分表的一些技巧。 分片技术的由来 关系型数据库本身比较容易成...

【PMP考试难点辨析】质量管理三大过程剖析及易错题总结(丁仿)

【PMP考试难点辨析】质量管理三大过程剖析及易错题总结 by——圣略PMP咨询顾问丁仿 很多学员在PMP的学习过程中,针对质量管理章节,三个过程极容易混淆。以下根据...

水平分库分表的关键步骤和技术难点

在之前的文章中,我介绍了分库分表的几种表现形式和玩法,也重点介绍了垂直分库所带来的问题和解决方法。本篇中,我们将继续聊聊水平分库分表的一些技巧。分片技术的由来关系型数据库本身比较容易成为系统性能瓶颈,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:链表题--难点
举报原因:
原因补充:

(最多只允许输入30个字)