• 快慢指针


    一、快慢指针说明

      快慢是指移动步数的长短,也就是每次向前移动速度的快慢。如,指定快指针每次沿着链表向前移动2步,指定慢指针每次沿着链表向前移动1步。

    二、快慢指针的应用

    1、判断单链表是否为循环链表

      首先设置快慢指针的起点为链表的头结点,快指针每次向前移动2步,慢指针每次向前移动1步。如果该链表为循环链表,则快指针会在不久之后追上慢指针;如果是单链表,则快指针会先到达链表的末尾。利用快慢指针解决这个问题还有一个好处是不必预先知道链表的长度。逻辑关系简单明了:快指针追上慢指针=>循环链表,快指针到达链尾=>单链表。

      1 #include<iostream>
      2 using namespace std;
      3 /* --- global variable --- */
      4 int n;
      5 int i;
      6 
      7 /* --- linked list struct --- */
      8 struct Node
      9 {
     10     int data; //node information
     11     Node* next = NULL; //next pointer
     12 };
     13 
     14 /* --- function prototypes --- */
     15 //create Circular/single linked list
     16 void CreatSing(Node *&head); //'&' means to change head
     17 void CreatCir(Node *&head);
     18 //judge the list
     19 
     20 void isCirOrSing(Node *head);
     21 
     22 /* --- main function --- */
     23 int main()
     24 {
     25 
     26     //define two head
     27     Node* headS = new Node();
     28     Node* headC = new Node();
     29 
     30     //create and judge single linked list
     31     CreatSing(headS);
     32     isCirOrSing(headS);
     33 
     34     cout<<endl<<" ---------- Luxuriant line ---------- "<<endl<<endl;
     35 
     36     //create and judge circular linked list
     37     CreatCir(headC);
     38     isCirOrSing(headC);
     39 
     40 
     41     return 0;
     42 }
     43 
     44 /* ---the key function--- */
     45 void isCirOrSing(Node *head)
     46 {
     47     Node *fast; //fast pointer, 2 steps/time
     48     Node *slow; //slow pointer, 1 step/time
     49     fast = slow = head; //start at head
     50     while(1)
     51     {
     52         //fast reach NULL => single
     53         if(fast->next==NULL||fast->next->next==NULL)
     54         {
     55             cout<<" single linked list !"<<endl;
     56             break;
     57         }
     58         //fast catch slow => circular
     59         else if(fast->next==slow||fast->next->next==slow)
     60         {
     61             cout<<" circular linked list !"<<endl;
     62             break;
     63         }
     64         else
     65         {
     66             fast = fast->next->next; //2 steps/time
     67             slow = slow->next; //1 step/time
     68         }
     69     }
     70 }
     71 
     72 void CreatSing(Node *&head)
     73 {
     74     Node* p = new Node();
     75     cout<<"input linked list number: ";
     76     cin>>n;
     77 
     78     head =p;
     79     cout<<"input linked list data list: ";
     80     for(i=0;i<n-1;i++)
     81     {
     82         cin>>p->data; //input data
     83         p->next = new Node();
     84         p = p->next; //link to next
     85     }
     86     cin>>p->data;
     87 
     88     //print to check
     89     cout<<endl;
     90     Node* q;
     91     q = head;
     92     int x = 10;
     93     while(q!=NULL)
     94     {
     95         cout<<q->data<<"->";
     96         q = q->next;
     97         x--;
     98     }
     99     cout<<"[NULL] "; //link NULL to the end
    100     q = NULL;
    101 }
    102 
    103 void CreatCir(Node *&head)
    104 {
    105     Node* p = new Node();
    106     cout<<"input linked list number: ";
    107     cin>>n;
    108 
    109     head =p;
    110     cout<<"input linked list data list: ";
    111     for(i=0;i<n;i++)
    112     {
    113         cin>>p->data; //input data
    114         if(i==n-1) //link the end to head
    115             p->next = head;
    116         else
    117         {
    118             p->next = new Node();
    119             p = p->next; //link to next
    120         }
    121     }
    122 
    123     //print to check
    124     cout<<endl;
    125     Node* q;
    126     q = head;
    127     int x = 10; //Output the length of 10 laps
    128     while(x!=0)
    129     {
    130         cout<<q->data<<"->";
    131         q = q->next;
    132         x--;
    133     }
    134     cout<<"... ";
    135     q = NULL;
    136 }

      运行输出结果:

    2、有序链表中寻找中位数

      快指针的移动速度是慢指针的2倍,所以快指针到达链表尾巴时,慢指针到达链表中点。

      有两种情况需要分开考虑,即链表为偶数长度时,和链表为计数长度时。(head结点依然存储数据)

      链表长度为偶数时,快指针只能到达链表的倒数第二个结点;则慢指针的位置为上中位数;因此返回(上中位数+下中位数)/2。

      链表长度为奇数时,快指针就能到达链表的最后一个结点;则慢指针的位置就是中位数;因此直接返回慢指针的值。

      例如,链表长度为4时,fast第一次移动后指向倒数第二个结点(data=3),slow第一次移动后指向第二个结点(data=2);

      进入判断fast->next->next是否为NULL,判断成立,当前slow位置在第二个结点处(data=2),因此返回(slow->data)+(slow->next->data)/2=2.5,即为所求中位数。

      又例如,链表长度为3时, fast第一次移动后指向最后一个结点(data=3),slow第一次移动后指向第二个结点(data=2);

      进入判断fast->next是否为NULL,判断成立,当前slow位置在第二个结点处(data=2),因此返回(slow->data)=2,即为所求中位数。

      代码实现:

     1 #include<iostream>
     2 using namespace std;
     3 /* --- global variable --- */
     4 int n;
     5 int i;
     6 
     7 /* --- linked list struct --- */
     8 struct Node
     9 {
    10     int data; //node information
    11     Node* next = NULL; //next pointer
    12 };
    13 
    14 /* --- function prototypes --- */
    15 void CreatSing(Node *&head); //'&' means to change head
    16 double findMedian(Node *head);
    17 
    18 /* --- main function --- */
    19 int main()
    20 {
    21     int x=2; //print twice
    22     while(x!=0)
    23     {
    24         x--;
    25 
    26         //define a head
    27         Node* head = new Node();
    28         //create a single linked list
    29         CreatSing(head);
    30         //find median
    31         double result = findMedian(head);
    32         //print the median
    33         cout<<" median = "<<result<<endl;
    34         cout<<endl<<" ---------- Luxuriant line ---------- "<<endl<<endl;
    35         head = NULL;
    36     }
    37 
    38     return 0;
    39 }
    40 
    41 /* ---the key function--- */
    42 double findMedian(Node *head)
    43 {
    44     Node *fast; //fast pointer, 2 steps/time
    45     Node *slow; //slow pointer, 1 step/time
    46     fast = slow = head; //start at head
    47     while(1)
    48     {
    49         if(fast->next==NULL) //odd
    50             return (slow->data);
    51         else if(fast->next->next==NULL) //even
    52             return ((slow->data)+(slow->next->data))/2.0;
    53         else
    54         {
    55             fast = fast->next->next; //2 steps/time
    56             slow = slow->next; //1 step/time
    57         }
    58     }
    59 }
    60 
    61 void CreatSing(Node *&head)
    62 {
    63     Node* p = new Node();
    64     cout<<"input linked list number: ";
    65     cin>>n;
    66 
    67     head = p;
    68     cout<<"input linked list data list: ";
    69     for(i=0;i<n-1;i++)
    70     {
    71         cin>>p->data; //input data
    72         p->next = new Node();
    73         p = p->next; //link to next
    74     }
    75     cin>>p->data;
    76 
    77     //print to check
    78     cout<<endl;
    79     Node* q;
    80     q = head;
    81     int x = 10;
    82     while(q!=NULL)
    83     {
    84         cout<<q->data<<"->";
    85         q = q->next;
    86         x--;
    87     }
    88     cout<<"[NULL] "; //link NULL to the end
    89     q = NULL;
    90 }

      运行输出结果:

  • 相关阅读:
    最简单的基于FFMPEG+SDL的音频播放器 ver2 (採用SDL2.0)
    JBPM——工作流概念
    android项目中的拍照和本地图片截图
    hunnu--11547--你的组合数学学得怎样?
    POJ 2253
    [ACM] POJ 3349 Snowflake Snow Snowflakes(哈希查找,链式解决冲突)
    Redis简述
    C/C++,从未过时的编程语言之父
    Android4.4 Framework分析——getContentResolver启动ContentProvider的过程
    2012_p2 寻宝 (treasure.cpp/c/pas)
  • 原文地址:https://www.cnblogs.com/Christal-R/p/7207421.html
Copyright © 2020-2023  润新知