快慢指针的概念及其应用
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; }
相关文章推荐
- C语言学习(六)——二重指针概念及其应用
- Storm概念、原理详解及其应用(二)Storm Cluster
- Storm概念、原理详解及其应用(一)BaseStorm
- (转)四元数概念及其应用
- redis概念、做什么及其应用场景
- OpenGL中FBO的概念及其应用
- ASP.NET缓存概念及其应用浅析
- JavaScript高级之闭包的概念及其应用
- 【C/C++学院】0823-静态联合编译与动态联合编译/父类指针子类指针释放/虚函数/纯虚函数概念以及虚析构函数/抽象类与纯虚函数以及应用/虚函数原理/虚函数分层以及异质链表/类模板的概念以及应用
- leetcode第143题 ( Reorder List),快慢指针的应用
- 快慢指针在链表的应用
- ASP.NET缓存概念及其应用浅析
- OpenGL中FBO的概念及其应用
- ASP.NET缓存概念及其应用浅析
- 程序包开发相关概念及其应用
- JUnit -- 概念及其应用
- ASP.NET缓存概念及其应用浅析
- OpenGL中FBO的概念及其应用
- 数据库的本质、概念及其应用实践(一)
- JavaScript高级之闭包的概念及其应用