判断一个单向链表中是否有环

       一段代码判断一个单向链表中是否有环。


下面为链表中的结构体节点
struct node
{
     int data;
     node *next;
}*linklist,*s,*t;

方法一:
    最简单的思路就是,定义一个指针数组,初始化为空指针,从链表的头指针开始往后遍历,每次遇到一个指针就跟指针数组中的指针相比较,若没有找到相同的指针,说明这个节点是第一次访问,还没有形成环,将这个指针添加到指针数组中去。若在指针数组中找到了同样的指针,说明这个节点已经被访问过了,于是就形成了环。


方法二:
    使用map来进行映射。首先定义 map<node*,int>m; 意思就是将一个node* 指针映射成数组的下标,并赋值为一个int类型的数值。
从链表的头指针开始往后遍历(p=p->next;),每次遇到一个指针p,就判断if(m[p]==0)  m[p]=1;说明这个节点是第一次访问,if(m[p]==1) 说明这个节点已经被访问过一次了,于是就形成了环。
#include "iostream"
#include "map"
using namespace std;
map<node*,int>m;
bool IsLoop(node *head)
{
      if(!head)
           return false;
      node *p=head;
      while(p)
     {
           if(m[p]==0) // 默认值都是0
                m[p]=1;
           else if(m[p]==1)
                return true;
           p=p->next;
     }
}
方法三:
思路:
    用两个指针,pSlow,pFast,就是一个慢一个快
    慢的一次跳一步
    快的一次跳两步
    往链表末端移动。如果pFast==NULL,则说明链表没有环,如果pSlow==pFast,则说明链表存在环。
    这个方法与前面2个方法相比,不但速度很快,而且不需要额外的存储空间,时间复杂度、空间复杂度都是最小的。
bool IsLoop(node *head)
{
        node *pSlow=head;
        node *pFast=head;
        while(pSlow!=NULL && pFast!=NULL)
        {
                pSlow=pSlow->next;
                pFast=pFast->next->next;
                if(pSlow==pFast)
                        return true;
        }
       return false;
}

完整的测试代码如下:

#include "iostream"
#include "map"
using namespace std;
struct node
{
      int data;
      struct node *next;
}*linklist,*s,*head;
map<node*,int>m;
bool IsLoop(node *head)
{
      node *pSlow=head;
      node *pFast=head;
      while(pSlow!=NULL && pFast!=NULL)
      {
            pSlow=pSlow->next;
            pFast=pFast->next->next;
            if(pSlow==pFast)
                 return true;
      }
      return false;
}
node* InsertNode(node *head,int value)
{
      if(head==NULL)
      {
            head=(node *)malloc(sizeof(node));
            if(head==NULL)
                  printf("malloc failed");
            else
            {
                  head->data=value;
                  head->next=NULL;
            }
       }
       else
       {
            node *temp=(node *)malloc(sizeof(node));
            if(temp==NULL)
                  printf("malloc failed");
            else
            {
                  temp->data=value;
                  temp->next=head;
                  head=temp;
             }
       }
       return head;
}
int main(void)
{
       node *t,*q,*p=NULL;
       p=InsertNode(p,8);
       p=InsertNode(p,7);
       p=InsertNode(p,6);
       p=InsertNode(p,5);
       p=InsertNode(p,4);
       q=p;
       p=InsertNode(p,3);
       p=InsertNode(p,2);
       p=InsertNode(p,1);
       t=p;
       while(t->next)       // 找到链表的尾指针
              t=t->next;
       t->next=q;           // 将链表的尾指针指向第四个节点,这样就构成了一个环
       bool flag=IsLoop(p);
       if(flag)
             cout<<"这个链表存在一个环"<<endl;
       else
             cout<<"这个链表不存在一个环"<<endl;
       system("pause");
       return 0;
}

1->2->3->4->5->6->7->8  最后8又指向了4,构成了一个环
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值