码迷,mamicode.com
首页 > 编程语言 > 详细

笔试,面试,C/C++,判断单链表是否带环?若带环,求环长度,求环入口点(两种方法)

时间:2016-01-05 01:37:54      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:笔试   面试   c/c++   判断单链表是否带环   求环长度   求环入口点   




SListNode* IsRing(SListNode *&pHead) //判断链表是否有环,求相聚点
{
 //判空、有、没有
 //思路:两个指针从头开始一快(2步)一慢(1步),若最后可以相聚,则链表有环
 if (pHead)
 {
  SListNode *fast = pHead;
  SListNode *slow = pHead;
  while (fast&&fast->next)
  {
   fast = fast->next->next;
   slow = slow->next;
   if (slow == fast)
    return fast;
  }
  return NULL;
 }
 return NULL;
}

int RingLength(SListNode *&pHead)//求链表环长度
{
 //先判断链表有环
 //思路:从IsRing得到的点开始走一圈环,记录结点个数
 if (pHead)//判空
 {
  SListNode* point = IsRing(pHead);
  if (point != NULL)//无环情况
  {
   int count = 1;
   SListNode *tmp = point->next;
   while (tmp != point)
   {
    tmp = tmp->next;
    count++;
   }
   return count;
  }
 }
 return 0;
}

SListNode* RingEntry(SListNode *&pHead)//找环入口
{
 //判是否为空、有环
 //思路:判断有环,找到快慢指针的相聚点,然后一个指针从聚点开始,一个从头开始,每次一步,相遇点就为入口节点

 if (pHead)//判空
 {
  SListNode *tmp = IsRing(pHead);
  if (tmp)//判有环
  {
   SListNode *cur = pHead;
   while (cur!=tmp)
   {
    cur = cur->next;
    tmp = tmp->next;
   }
   return cur;
  }
  return NULL;
 }
 return NULL;
}

int _LengthNode(SListNode*& pHead)//RingEntry_Point内部函数,求链表长度
{
 if (pHead)
 {
  SListNode *tmp = pHead;
  int count = 0;
  while (tmp)
  {
   count++;
   tmp = tmp->next;
  }
  return count;
 }
 return 0;
}
SListNode* RingEntry_Point(SListNode *&pHead)//找环入口_链表相交法
{
 //判是否为空、有环
 //思路:在快慢指针相聚点截断,将环链表变为两个相交链表,因为相交链表尾部重合呈Y字型,
 //     求两个链表长度之差K,再令一个指针从长链表开始先走K步,令另一个指针从短链表头开始,
 //     两链表一起走,相遇点就为入口点
 //
 //经过调试发现 当整个链表呈环时,为特殊情况
 if (pHead)//判空
 {
  SListNode *tmp = IsRing(pHead);
  if (tmp)//判有环
  {
   SListNode *cur = pHead;
   SListNode *NewNode = tmp->next;
   tmp->next = NULL;
   int c1 = _LengthNode(cur);
   int c2 = _LengthNode(NewNode);
   int minus = _LengthNode(cur) - _LengthNode(NewNode);
   if (minus > 0)
   {
    while (minus--)
    {
     cur = cur->next;
    }
   }
   else
   {
    int tmp = -minus;
    while (tmp--)
    {
     NewNode = NewNode->next;
    }
   }

   while (NewNode!=cur)
   {
    NewNode = NewNode->next;
    cur = cur->next;
   }
   return cur;
  }
  return NULL;
 }
 return NULL;
}


void Test9()  //IsRing/RingLength/RingEntry_1/RingEntry_2
{
 printf("//Test9() IsRing/RingLength/RingEntry/RingEntry_Point \n");
 SListNode *LL = NULL;
 PushBack(LL, 1);
 PushBack(LL, 2);
 PushBack(LL, 3);
 PushBack(LL, 4);
 PushBack(LL, 5);
 PrintNode(LL);
 //printf("%d\n", _LengthNode(LL));

 printf("\nRingLength = %d\n", RingLength(LL));//不是环
 SListNode*tmp = RingEntry(LL);
 PrintNode(tmp);
 tmp = RingEntry_Point(LL);
 PrintNode(tmp);

 Find(LL, 5)->next = Find(LL, 5);//尾结点呈环
 printf("\nRingLength = %d\n", RingLength(LL));
 printf("RingEntry = %d\n", RingEntry(LL)->data);
 printf("RingEntry_Point = %d\n", RingEntry_Point(LL)->data);

 Find(LL, 5)->next = Find(LL, 3);//中间结点开始呈环
 printf("\nRingLength = %d\n", RingLength(LL));
 printf("RingEntry = %d\n", RingEntry(LL)->data);
 printf("RingEntry_Point = %d\n", RingEntry_Point(LL)->data);//函数RingEntry_Point在此处将原链表破坏丢失元素5

 //Find(LL, 5)->next = Find(LL, 1);//整个链表为环链表已不存在元素为5的结点 出现错误
 Find(LL, 4)->next = Find(LL, 1);//整个链表为环
 printf("\nRingLength = %d\n", RingLength(LL));
 printf("RingEntry = %d\n", RingEntry(LL)->data);
 printf("RingEntry_Point = %d\n", RingEntry_Point(LL)->data);
}


技术分享

笔试,面试,C/C++,判断单链表是否带环?若带环,求环长度,求环入口点(两种方法)

标签:笔试   面试   c/c++   判断单链表是否带环   求环长度   求环入口点   

原文地址:http://10739786.blog.51cto.com/10729786/1731559

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!