一.概念
快慢指针中的快慢是指移动的步长,及每次向前移速度的快慢。例如:快指针每次沿链表向前移动2,慢指针每次向前移动1.
二.应用
- 判断单链表是否有环
假设链表存在环,此时定义两个指针,一个指针每次向前移动两个位置(快指针),另一个指针每次向前移动一步(慢指针),若快指针到达NULL,则说明链表以NULL结尾,没有环。如果快指针追上慢指针,则表示该链表有环。
代码实现:
#include <iostream>
using namespace std;
typedef struct Node
{
char c;
struct Node *next;
}Node, *LinkList;
void PutOut(LinkList H)
{
LinkList p;
p = H->next;
while (p)
{
cout << p->c << " ";
p = p->next;
}
cout << endl;
}
bool HasLoop(Node *H)
{
Node *slow = H;
Node *fast = H;
while (fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
cout << "此链表有环!" << endl;
return true;
}
}
if (fast->next == NULL)
{
cout << "此链表无环!" << endl;
return false;
}
}
int main(void)
{
LinkList H = new Node();
Node d = { 'd', NULL };
Node c = { 'c', &d };
Node b = { 'b', &c };
Node a = { 'a', &b };
H->next = &a;
PutOut(H);
HasLoop(H);
LinkList New_H = new Node();
Node A, B, C, D;
A.c = 'A';
B.c = 'B';
C.c = 'C';
D.c = 'D';
New_H->next = &A;
A.next = &B;
B.next = &C;
C.next = &D;
D.next = &B;
HasLoop(New_H);
return 0;
}
- 在有序链表中寻找中位数
原理:由于快指针的移动速度是慢指针的2倍,所以当快指针到达链表尾时,慢指针正好到达链表中点。可以不借助计数器实现寻找中位数的功能。 - 输出链表中的倒数第K个结点
原理:定义两个指针,第一个指针从链表的头指针开始遍历向前走k-1步,第二个指针保持不动;从第k步开始,第二个指针也开始从头指针遍历,由于两个指针的距离保持在k-1,当第一个指针到达链表尾时,第二个指针正好指向链表的倒数第k个结点。
代码实现:
#include <iostream>
#include <malloc.h>
using namespace std;
typedef struct Node
{
char c;
struct Node *next;
}Node, *LinkList;
void PutOut(LinkList H)
{
LinkList p;
p = H->next;
while (p)
{
cout << p->c << " ";
p = p->next;
}
cout << endl;
}
void Rec_K(LinkList L, int K)
{
LinkList pre, late;
pre = L;
late = L;
int i;
for (i = 0; i < K-1; ++i)
{
pre = pre->next;
}
while (pre->next != NULL)
{
pre = pre->next;
late = late->next;
}
cout << "倒数第" << K << "个结点的值为" << late->c << endl;
}
int main(void)
{
LinkList H = new Node();
Node d = { 'd', NULL };
Node c = { 'c', &d };
Node b = { 'b', &c };
Node a = { 'a', &b };
H->next = &a;
PutOut(H);
Rec_K(H, 2);
return 0;
}
- 判断两个单向链表是否相交,若相交,找出它们的第一个公共结点
原理:分别遍历两个链表到末尾,若末尾结点相同,则说明它们相交,否则不相交。
代码验证:
#include <iostream>
using namespace std;
typedef struct NODE
{
int data;
struct NODE *next;
}Node,*LinkList;
LinkList InitList()
{
LinkList H;
H = (LinkList)malloc(sizeof(LinkList));
H->next = NULL;
return H;
}
void CreatByTail_X(LinkList A, LinkList B, LinkList C)
{
int i = 1, j = 1, k = 1;
Node *pA, *pB, *pC, *tail_A, *tail_B, *tail_C;
tail_A = A;
tail_B = B;
tail_C = C;
while (i <= 5)
{
pA = (Node*)malloc(sizeof(Node));
pA->data = i + 3;
pA->next = tail_A->next;
tail_A->next = pA;
tail_A = tail_A->next;
i++;
}
tail_A->next = NULL;
while (j <=3 )
{
pB = (Node*)malloc(sizeof(Node));
pB->data = j;
tail_B->next = pB;
tail_B = tail_B->next;
j++;
}
i = 0;
pA = A;
while (i < 4)
{
pA = pA->next;
i++;
}
tail_B->next = pA;
while (k <= 6)
{
pC = (Node*)malloc(sizeof(Node));
pC->data = k;
pC->next = tail_C->next;
tail_C->next = pC;
tail_C = tail_C->next;
k++;
}
tail_C->next = NULL;
}
void PutOut(LinkList L)
{
Node *p;
p = L->next;
while (p != NULL)
{
cout << p->data << " -> ";
p = p->next;
}
cout << "\b\b\b\b " << endl;
}
void Is_InterSert(LinkList _A, LinkList _B)
{
Node *_pA, *_pB;
_pA = _A;
_pB = _B;
while (_pA != NULL && _pB != NULL)
{
_pA = _pA->next;
_pB = _pB->next;
if (_pA == _pB)
{
cout << "相交了!" << endl;
break;
}
}
if (_pA != _pB)
{
cout << "未相交!" << endl;
}
}
int main(void)
{
LinkList A;
A = InitList();
LinkList B;
B = InitList();
LinkList C;
C = InitList();
CreatByTail_X(A, B, C);
cout << "链表A:" << endl;
PutOut(A);
cout << "链表B:" << endl;
PutOut(B);
cout << "链表C:" << endl;
PutOut(C);
cout << "A 与 B";
Is_InterSert(A, B);
cout << "A 与 C";
Is_InterSert(A, C);
cout << "B 与 C";
Is_InterSert(B, C);
return 0;
}