您的位置:首页 > 理论基础 > 数据结构算法

快慢指针的概念及其应用

2017-07-23 19:05 357 查看

一.概念

快慢指针中的快慢是指移动的步长,及每次向前移速度的快慢。例如:快指针每次沿链表向前移动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;
/*
若第一个指针先走 K 步,则两个指针同时移动时的循环条件是while(p != NULL)
若第一个指针先走 K-1 步,则两个指针同时移动时的循环条件是 while(p->next != NULL)
*/
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;
}
//创建两条相交链表(V形或者Y形,不可能是X形,因为相交后,后续结点都一致)
//再创建一条与之都不相交的链表来进行验证
void CreatByTail_X(LinkList A, LinkList B, LinkList C)
{
int i = 1, j = 1, k = 1;
Node *pA, *pB, *pC, *tail_A, *ta
4000
il_B, *tail_C;
tail_A = A;
tail_B = B;
tail_C = C;

//建立链表A
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;

//建立链表B
while (j <=3 )
{
pB = (Node*)malloc(sizeof(Node));
pB->data = j;
tail_B->next = pB;
tail_B = tail_B->next;
j++;
}
//使pA从头结点开始后移,记录第四个结点位置,让tail_B指向它,则构成相交链表
i = 0;
pA = A;
while (i < 4)
{
pA = pA->next;
i++;
}
tail_B->next = pA;

//建立链表C
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 单链表