给定一个单链表,只给出头指针h:
1、如何判断是否存在环?
2、如何知道环的长度?
3、如何找出环的连接点在哪里?
4、带环链表的长度是多少?
解法:
1、对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。
2、对于问题2,记录下问题1的碰撞点p,slow、fast从该点开始,再次碰撞所走过的操作数就是环的长度s。
3、问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
该定理的证明可参考:http://fayaa.com/tiku/view/7/
4、问题3中已经求出连接点距离头指针的长度,加上问题2中求出的环的长度,二者之和就是带环单链表的长度
判断是否存在环的程序:
bool IsExitsLoop(slist *head) { slist *slow = head, *fast = head; while ( fast && fast->next ) { slow = slow->next; fast = fast->next->next; if ( slow == fast ) break; } return !(fast == NULL || fast->next == NULL); }
寻找环连接点(入口点)的程序:
slist* FindLoopPort(slist *head) { slist *slow = head, *fast = head; while ( fast && fast->next ) { slow = slow->next; fast = fast->next->next; if ( slow == fast ) break; } if (fast == NULL || fast->next == NULL) return NULL; slow = head; while (slow != fast) { slow = slow->next; fast = fast->next; } return slow; }
完整演示程序:
#include "stdio.h" #include "stdlib.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef int Status; typedef int ElemType; typedef struct Node{ ElemType data; struct Node* next; }Node; Status initList(Node** L){ *L = (Node*)malloc(sizeof(Node)); if(!(*L)){ return ERROR; } (*L)->next = NULL; return OK; } int listLength(Node* L){ int i = 0; Node* p = L->next; while(p){ i++; p = p->next; } return i; } // Non-Chain void createListHead(Node** L, int n){ Node* p; int i; srand(time(0)); *L = (Node*)malloc(sizeof(Node)); (*L)->next = NULL; for(i=0; i<n; i++){ p = (Node*)malloc(sizeof(Node)); // p->data = rand()%100+1; p->data = i+1; p->next = (*L)->next; (*L)->next = p; } } // Chain void createListTail(Node** L, int n){ Node* p, *r; int i; srand(time(0)); *L = (Node*)malloc(sizeof(Node)); r = *L; for(i=0; i<n; i++){ p = (Node*)malloc(sizeof(Node)); // p->data = rand()%100+1; p->data = i+1; r->next = p; r = p; } // 把尾节点与第二个节点连接起来 r->next = (*L)->next->next; } // 用两个指针cur1,cur2, cur1每次前进一个pos,cur2每次重头前进直到和cur1指向相同的节点, // 再比较两者经过的步数是否相等 int hasLoop1(Node* L){ Node* cur1 = L; int pos1 = 0; while(cur1){ Node* cur2 = L; int pos2 = 0; while(cur2){ if(cur2 == cur1){ if(pos1 == pos2){ break; } else{ printf("Chain is in the %d place\n\n", pos2); return 1; } } cur2 = cur2->next; pos2++; } cur1 = cur1->next; pos1++; } return 0; } // 快慢指针,如果相等则说明有环 int hasLoop2(Node* L){ int step1 = 1; int step2 = 2; Node* p = L; Node* q = L; while(p!=NULL && q!=NULL && q->next!=NULL){ p = p->next; q = q->next->next; printf("p:%d, q:%d \n", p->data, q->data); // 找到相碰点 if(p == q){ return 1; } } return 0; } // 寻找环连接点(入口点) Node* findLoopEntry(Node* L){ Node* slow = L, *fast=L; while(fast && slow && fast->next){ slow = slow->next; fast = fast->next->next; // 找到相碰点 if(slow == fast){ printf("Collision point value is %d\n", slow->data); break; } } if(fast==NULL || fast->next==NULL){ return NULL; } // 碰撞点p到连接点的距离=头指针到连接点的距离 slow = L; while(slow != fast){ slow = slow->next; fast = fast->next; } return slow; } int main(){ Node* L; Status i; char opp; ElemType e; int find; int tmp; i = initList(&L); printf("After initialization, listLength(L)=%d\n", listLength(L)); printf("\n1.Create Chain Linked list(Tail Insert) \n2.Create Non-Chain Linked List(Head Insert) \n3.Judge if a chain exists \n0.Exit\n\n"); while(opp != '0'){ scanf("%c", &opp); switch(opp){ case '1': createListTail(&L, 10); printf("Create Chain LinkedList L(Tail Insert) OK\n"); printf("\n"); break; case '2': createListHead(&L, 10); printf("Create Non-Chain Linked List(Head Insert) OK\n"); printf("\n"); break; case '3': printf("Solution 1: \n\n"); if(hasLoop1(L)){ printf("Summary: Chain exists\n\n"); } else{ printf("Summary: No Chain\n\n"); } printf("---------------------------\n\n"); printf("Solution 2: \n\n"); if(hasLoop2(L)){ printf("Summary: Chain exists\n\n"); Node* entry = findLoopEntry(L); printf("Entry value is: %d\n", entry->data); } else{ printf("Summary: No Chain\n\n"); } } } }
相关推荐
判断单链表是否有环是指检测链表中是否存在环的操作。例如,链表1->2->3->4->5->3是一个有环的链表,因为链表中存在环。 解决方案: ```c bool IsExitsLoop(NodeList head){ NodeList slow=head,fast=head; ...
- NEC公司的技术笔试包括选择题、编程题、逻辑推理题等多种题型,这些题型涉及到数据结构、算法、计算机网络、操作系统和编程语言等多方面的知识点。 以上知识点涵盖了文件中提到的大部分内容,并对每个知识点进行...
### 2008校园招聘部分500强笔试题解析 #### 一、哈希函数冲突问题(选择题) **题目描述**: 在以下哪个使用场景中,所给出的哈希函数会导致较大的冲突? A. 使用手机号码的最后两位数字作为哈希值,用于公共客户...
题目询问如何检测单链表是否存在环。常用算法是Floyd判环法,也称为“龟兔赛跑”算法。设置快慢两个指针,快指针每次移动两步,慢指针每次移动一步。如果链表存在环,则快慢指针最终会在环内相遇;若不存在环,快...
假设链表的长度为n,那么可以使用两个指针,一个指针从头节点开始移动,另一个指针从头节点移动两倍的速度,如果两个指针相遇,则链表中存在环。 9. 判断两个单链表是否相交 可以使用哈希表来解决这个问题。首先...
这个问题的关键在于理解快慢指针会相遇的原理,以及如何利用这个原理来判断链表中是否存在环。 题二检测两个单链表是否有交点的知识点: 对于检测两个链表是否有交点的问题,首先需要考虑特殊情况,即两个链表的头...
8. **AOV网和拓扑排序**:AOV网是活动-on-vertex的缩写,表示顶点间的有向无环图,通过拓扑排序可以检查图中是否存在环。 9. **二叉树遍历**:二叉树的遍历包括前序遍历(根-左-右)、中序遍历(左-根-右)和后序...
同时,存在多个`if`条件判断语句,用于检查数组中的值是否为特定的空值(假设使用null表示空指针),这些都是基础的程序设计逻辑。 3. 指针和引用 文档中的代码使用了指针来访问和操作数据结构中的元素。例如,指针...