关闭

链表题--难点

标签: 链表指针plistC语言
151人阅读 评论(3) 收藏 举报
分类:
  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;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:2733次
    • 积分:284
    • 等级:
    • 排名:千里之外
    • 原创:26篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论