zoukankan      html  css  js  c++  java
  • 判断单链表中是否有环(循环链表)

    有环的定义:链表的尾结点指向了链表中的某个结点,如下图所示

    判断是否有环,两种方法:

    方法1:使用p、q两个指针,p总是向前走,但q每次都从头开始走,对于每个节点看p走的步数和q是否一样,如上图所示:当p从6走到3时,共走了6步,此时若q从出发,则q只需要走两步就到达3的位置,因而步数不相等,出现矛盾,存在环。

    方法2:快慢指针,定义p、q两个指针,p指针每次向前走一步,q每次向前走两步,若在某个时刻出现 p == q,则存在环。

    具体代码实现:

      1 #include<stdio.h>
      2 #include<iostream>
      3 #include<stdlib.h>
      4 #include<string.h>
      5 #include<malloc.h>
      6 #include<time.h>
      7 using namespace std;
      8 
      9 #define OK 1
     10 #define ERROR 0
     11 #define TRUE 1
     12 #define FALSE 0
     13 
     14 typedef struct Node{
     15     int data;
     16     struct Node *next;
     17 }Node,*LinkList;
     18 
     19 int InitList(LinkList &L){//初始化带头结点的空链表 
     20     L = (LinkList)malloc(sizeof(Node));//产生头结点,并使L指向此头结点 
     21     if(!L)//如果存储分配失败 
     22         return ERROR;
     23     L->next = NULL;//指针域为空 
     24     return OK;
     25 }
     26 
     27 int ListLength(LinkList &L){//返回链表L中数据元素个数 
     28     int i = 0;
     29     LinkList p;
     30     p = L->next;
     31     while(p){
     32         i++;
     33         p = p->next;
     34     }
     35     return i; 
     36 }
     37 
     38 //随机产生n个元素的值,建立带头结点的单链表L(头插法) 
     39 void CreateListHead(LinkList &L, int n){
     40     LinkList p;
     41     srand(time(0));
     42     for(int i = 0; i < n; i++){
     43         p = (LinkList)malloc(sizeof(Node));
     44         p->data = rand()%100+1;
     45         p->next = L->next;
     46         L->next = p; 
     47     }
     48 } 
     49 
     50 //随机产生n个元素的值,建立带头结点的单链表L(尾插法) 
     51 void CreateListTail(LinkList &L, int n){
     52     LinkList r,p;
     53     r = L;
     54     srand(time(0));//初始化随机数种子
     55     for(int i = 0; i < n; i++){
     56         p = (LinkList)malloc(sizeof(Node));
     57         p->data = rand()%100+1;//随机产生100以内的数字
     58         r->next = p;
     59         r = p; 
     60     } 
     61     r->next = NULL;
     62     p->next = L->next->next;//成环 
     63 }
     64 
     65 //比较步数的方法 
     66 int HasLoop1(LinkList &L)
     67 {
     68     LinkList cur1 = L;//定义结点cur1 
     69     int post1 = 0;//cur1的步数
     70     while(cur1)
     71     {//cur1结点存在 
     72         LinkList cur2 = L;//定义结点cur2
     73         int post2 = 0;//cur2的步数
     74         while(cur2)
     75         {//cur2结点存在 
     76             if(cur2 == cur1)
     77             {//当cur1和cur2达到相同结点时 
     78                 if(post1 == post2)//走过的步数一样 
     79                     break;//则没有环 
     80                 else//否则 
     81                 {
     82                     printf("环的位置在第%d个结点处。",post2);
     83                     return 1;    
     84                 }
     85             }
     86             cur2 = cur2->next;//如果没有发现环,则继续下一个结点
     87             post2++;//cur2步数自增1     
     88         }
     89         cur1 = cur1->next;//cur1继续向后一个结点 
     90         post1++;//cur2步数自增1    
     91     }
     92     return 0; 
     93 }
     94 
     95 //利用快慢指针的方法
     96 int HasLoop2(LinkList &L){
     97     int step1 = 1;
     98     int step2 = 2;
     99     LinkList p = L;
    100     LinkList q = L;
    101     while(p != NULL && q != NULL && q->next != NULL){
    102         p = p->next;
    103         if(p->next != NULL)
    104             q = q->next->next;
    105         printf("p:%d,q:%d
    ",p->data,q->data);
    106         if(p == q)
    107             return 1;
    108     }
    109     return 0;
    110 } 
    111 
    112 int main(){
    113     LinkList L;
    114     InitList(L); 
    115     int i,e,find,temp;
    116     char opp;
    117     i = InitList(L);
    118     printf("初始化L后,ListLength(L)=%d
    ",ListLength(L));
    119     printf("
    1.创建有环链表(尾插法)
    2.创建无环链表(头插法)
    3.判断链表是否有环 
    0.退出
    
    请选择你要的操作:
    ");
    120     while(opp != '0'){
    121         scanf("%c",&opp);
    122         switch(opp){
    123             case '1':
    124                 CreateListTail(L,10);
    125                 printf("成功创建有环链表L(尾插法)
    ");
    126                 printf("
    ");
    127                 break;
    128                 
    129             case '2':
    130                 CreateListHead(L,10);
    131                 printf("成功创建无环链表L(头插法)
    ");
    132                 printf("
    ");
    133                 break;
    134             
    135             case '3':
    136                 printf("方法一:
    
    ");
    137                 if(HasLoop1(L)){
    138                     printf("结论:链表有环
    
    
    ");
    139                 }
    140                 else{
    141                     printf("结论:链表无环
    
    
    ");
    142                 }
    143                 printf("方法二:
    
    ");
    144                 if(HasLoop2(L)){
    145                     printf("结论:链表有环
    
    
    ");
    146                 }
    147                 else{
    148                     printf("结论:链表无环
    
    
    ");
    149                 }
    150                 printf("
    "); 
    151                 break;
    152             case '4':
    153                 exit(0);     
    154         }
    155     } 
    156     return 0;
    157 }

    运行结果:

  • 相关阅读:
    今天玩wow的时候遇到的事,汗!
    EF4.0数据DateTime2数据类型错误
    在64位windows server 2003的IIS6上运行32位的.NET程序
    CS0016: 未能写入输出文件“c:\WINDOWS\Microsoft.NET\Framework\.。。”“拒绝访问
    [转]网银支付接口编程资料汇总
    [转]Asp.Net MVC之ViewData字典与ViewModel模式
    MVC3小技巧
    MVC3+Spring.net+NHibernate+ExtJs的简单架构
    我的程序之路 asp.net 接触二年,工作一年总结 (2) lcs
    ASPXspy2.aspx lcs
  • 原文地址:https://www.cnblogs.com/geziyu/p/9903952.html
Copyright © 2011-2022 走看看