链表题--难点

原创 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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

链表相关的算法题大汇总 — 数据结构之链表奇思妙想

声明:转自http://hi.baidu.com/lanxuezaipiao/item/afc616caf8393a155050585b 基本函数 1,构造节点:  //定义节点类型 struct...
  • lanxuezaipiao
  • lanxuezaipiao
  • 2014年03月25日 21:18
  • 2814

链表经典算法题实现

本文包含链表的以下内容:   1、单链表的创建和遍历   2、求单链表中节点的个数   3、查找单链表中的倒数第k个结点(剑指offer,题15)   4、查找单链表中的中间结点   5、合...
  • u012129558
  • u012129558
  • 2016年09月18日 16:29
  • 941

hdu1412(水题 用一下链表做){A} + {B}.

Problem Description 给你两个集合,要求{A} + {B}. 注:同一个集合中不会有两个相同的元素. Input 每组输入数据分为三行,第一行有两个数字n,m(0 ...
  • u010372095
  • u010372095
  • 2013年07月29日 00:03
  • 1023

写的很好 链表的各种题目整理(C语言实现)

这里处理的全部是单链表: typedef struct node { char *data; struct node *next; } node_t; 我们约定一个打...
  • hongkangwl
  • hongkangwl
  • 2014年04月03日 21:25
  • 4808

数据结构学习笔记(六)链表算法题

第一题 问题 设顺序表用数组A[]表示,表中元素存储在数组下标1~m+n的范围内,前m个元素递增有序,后n个元素递增有序,设计一个算法,使得整个顺序表有序。 (1)给出算法的基本设计思想...
  • daweiwangzi
  • daweiwangzi
  • 2015年02月25日 17:42
  • 206

ACM-杭电 HDOJ-1216 模拟,链表

用下面的方法模拟,最开始开50000的链表跑了187ms,真是相当的惭愧呀。后改用35000的链表跑了109ms。最后改用c的输入输出(也就是下面放出的代码)跑了78ms,其实自己写链表会跑的更快。不...
  • lancegentry
  • lancegentry
  • 2012年09月24日 00:25
  • 2422

链表刷题总结-技巧以及注意事项

技巧: 1.插入头节点的技巧,诸如:删除链表中重复节点的题,反转链表某个区间的题等,通过插入头节点,可以使得对头节点的操作同后面节点的操作一样; 2.设置一快一慢指针,诸如:判断一个链表是否有环,有环...
  • shanshanhi
  • shanshanhi
  • 2017年03月13日 20:04
  • 586

链表操作 算法面试题

1、给定单链表的头指针和一个结点指针,在O(1)时间删除该结点。 算法描述:删除单链表的一个节点需要知道该节点的前驱和后继。实际上找到前驱的平局时间复杂化度就是O(1). 传送阵:http:/...
  • zzhays
  • zzhays
  • 2012年07月12日 14:04
  • 1271

链表总结----链表面试题合集

1、单链表基本操作 2、双链表基本操作 3、循环单链表基本操作 4、反转单链表 5、查找单链表倒数第K个节点 6、倒序打印链表 7、查找链表中间节点 8、删除链表第K个节点,平均时间复杂度为O(1) ...
  • beitiandijun
  • beitiandijun
  • 2014年12月13日 23:25
  • 1865

【ACM】【链表】关于在链表中实现…

设计思想: 相对于数据结构为数组的插入排序方法,现在要解决的是如何实现链表中的插入排序。数组的存储方式是顺序存储,而链表的存储方式是链式存储。所以,要实现针对链表的插入排序法,其关键是解决如何能够保...
  • nono_thin
  • nono_thin
  • 2013年12月03日 11:12
  • 941
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:链表题--难点
举报原因:
原因补充:

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