本篇主要介绍快慢指针。

快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢。例如可以让快指针每次沿链表向前移动2次,慢指针每次向前移动1次。

一、快慢指针的经典应用:判断一个链表是否存在环

思路:

1、使用快慢指针,慢指针每次走一步,快指针每次走两步。

2、快指针有两种状态:

当链表无环时,快指针走到末尾,这时退出循环;

当链表有环时,快指针就一直走,直到慢指针快指针追上慢指针时,退出循环。

注意:链表的长度分为奇数和偶数,所以快指针没走一步都要判断是否到达末尾(无环时)。

代码如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <time.h>
 5 
 6 typedef struct tag
 7 {
 8     int Nnum_;
 9     struct tag *Nnext_;
10 }Node, *pNode;
11 
12 
13 void link_print(pNode phead, int size)
14 {
15     int i= 0;
16     while(phead != NULL)
17     {
18         printf("%4d", phead->Nnum_);
19         phead = phead->Nnext_;
20         if( ++i > size)
21             break;
22     }
23     printf("\n");
24 }
25 //尾插法
26 void link_init_tail(pNode *phead, int size) //传的是地址
27 {
28     pNode pNew = NULL;
29     pNode pTail = NULL;
30 
31     while( size > 0)
32     {
33         //申请内存
34         pNew = (pNode)malloc(sizeof(Node)); //注意这里为何不用pNode而用Node,因为sizeof(pNode) = 4
35         //赋值
36         pNew->Nnum_ = rand()%1000;
37         //插入链表
38         if(*phead == NULL) //链表为空时
39         {
40             *phead = pNew;//连接新的结点
41             pTail = pNew;
42         }
43         else//不为空
44         {
45             pTail->Nnext_ = pNew ; //连接新的结点
46              pTail = pNew; //改名字
47         }    
48         size --;
49     }
50 /*
51     //生成一个带环的链表
52     pNode pCur = *phead;
53     int i =0;
54     while( i < 3) //attention
55     {
56         pCur = pCur->Nnext_;
57         i++;
58     }
59     pTail->Nnext_ = pCur; //生成一个环
60 */
61 }
62 
63 int isloop( pNode phead)
64 {
65     pNode pFast = phead; //快指针
66     pNode pSlow = phead; //慢指针
67 
68     while( pFast->Nnext_ != NULL)
69     {    
70         pSlow = pSlow->Nnext_;
71         pFast = pFast->Nnext_;
72         pFast = pFast->Nnext_; 
73         if(pFast == NULL)//没有这句的话,若length为偶数,则会Segmentation fault (core dumped)
74             return 0;
75 
76         if( pSlow == pFast) //有环存在
77             return 1;
78     }
79 
80     if( pFast == NULL) //无环
81         return 0;
82 } 
83 
84 int main(int argc, char const *argv[])
85 {
86     srand(time(NULL));
87     pNode phead = NULL;
88     link_init_tail(&phead, 10); //10为初始链表的长度
89     //从init中可以看出,若真正打印出的数字的长度为15(> 链表的初始长度),则说名存在环
90     link_print(phead,15); 
91 
92     printf(" ret:%d\n", isloop(phead));
93 
94     return 0;
95 }
View Code

相关文章: