笔试,面试,C/C++,判断单链表是否带环?若带环,求环长度,求环入口点(两种方法)
来源:互联网 发布:无法备案的域名 编辑:程序博客网 时间:2024/06/02 00:18
SListNode* IsRing(SListNode *&pHead) //判断链表是否有环,求相聚点{ //判空、有、没有 //思路:两个指针从头开始一快(2步)一慢(1步),若最后可以相聚,则链表有环 if (pHead) { SListNode *fast = pHead; SListNode *slow = pHead; while (fast&&fast->next) { fast = fast->next->next; slow = slow->next; if (slow == fast) return fast; } return NULL; } return NULL;}int RingLength(SListNode *&pHead)//求链表环长度{ //先判断链表有环 //思路:从IsRing得到的点开始走一圈环,记录结点个数 if (pHead)//判空 { SListNode* point = IsRing(pHead); if (point != NULL)//无环情况 { int count = 1; SListNode *tmp = point->next; while (tmp != point) { tmp = tmp->next; count++; } return count; } } return 0;}SListNode* RingEntry(SListNode *&pHead)//找环入口{ //判是否为空、有环 //思路:判断有环,找到快慢指针的相聚点,然后一个指针从聚点开始,一个从头开始,每次一步,相遇点就为入口节点 if (pHead)//判空 { SListNode *tmp = IsRing(pHead); if (tmp)//判有环 { SListNode *cur = pHead; while (cur!=tmp) { cur = cur->next; tmp = tmp->next; } return cur; } return NULL; } return NULL;}int _LengthNode(SListNode*& pHead)//RingEntry_Point内部函数,求链表长度{ if (pHead) { SListNode *tmp = pHead; int count = 0; while (tmp) { count++; tmp = tmp->next; } return count; } return 0;}SListNode* RingEntry_Point(SListNode *&pHead)//找环入口_链表相交法{ //判是否为空、有环 //思路:在快慢指针相聚点截断,将环链表变为两个相交链表,因为相交链表尾部重合呈Y字型, // 求两个链表长度之差K,再令一个指针从长链表开始先走K步,令另一个指针从短链表头开始, // 两链表一起走,相遇点就为入口点 // //经过调试发现 还必须在返回之前将链表复原,不然会出现丢失链表结点的情况,应对函数进行修改 if (pHead)//判空 { SListNode *tmp = IsRing(pHead); if (tmp)//判有环 { SListNode *cur = pHead; SListNode *NewNode = tmp->next; tmp->next = NULL; int c1 = _LengthNode(cur); int c2 = _LengthNode(NewNode); int minus = _LengthNode(cur) - _LengthNode(NewNode); if (minus > 0) { while (minus--) { cur = cur->next; } } else { int tmp = -minus; while (tmp--) { NewNode = NewNode->next; } } while (NewNode!=cur) { NewNode = NewNode->next; cur = cur->next; } return cur; } return NULL; } return NULL;}void Test9() //IsRing/RingLength/RingEntry_1/RingEntry_2{ printf("//Test9() IsRing/RingLength/RingEntry/RingEntry_Point \n"); SListNode *LL = NULL; PushBack(LL, 1); PushBack(LL, 2); PushBack(LL, 3); PushBack(LL, 4); PushBack(LL, 5); PrintNode(LL); //printf("%d\n", _LengthNode(LL)); printf("\nRingLength = %d\n", RingLength(LL));//不是环 SListNode*tmp = RingEntry(LL); PrintNode(tmp); tmp = RingEntry_Point(LL); PrintNode(tmp); Find(LL, 5)->next = Find(LL, 5);//尾结点呈环 printf("\nRingLength = %d\n", RingLength(LL)); printf("RingEntry = %d\n", RingEntry(LL)->data); printf("RingEntry_Point = %d\n", RingEntry_Point(LL)->data); Find(LL, 5)->next = Find(LL, 3);//中间结点开始呈环 printf("\nRingLength = %d\n", RingLength(LL)); printf("RingEntry = %d\n", RingEntry(LL)->data); printf("RingEntry_Point = %d\n", RingEntry_Point(LL)->data);//由于函数实现时没有将断开的环闭合,导致丢失数据 //函数RingEntry_Point在此处将原链表破坏丢失元素5 //Find(LL, 5)->next = Find(LL, 1);//整个链表为环链表已不存在元素为5的结点 出现错误 Find(LL, 4)->next = Find(LL, 1);//整个链表为环 printf("\nRingLength = %d\n", RingLength(LL)); printf("RingEntry = %d\n", RingEntry(LL)->data); printf("RingEntry_Point = %d\n", RingEntry_Point(LL)->data);}
对函数SListNode* RingEntry_Point(SListNode *&pHead)进行修改后
SListNode* RingEntry_Point(SListNode *&pHead)//找环入口_链表相交法{ //判是否为空、有环 //思路:在快慢指针相聚点截断,将环链表变为两个相交链表,因为相交链表尾部重合呈Y字型, // 求两个链表长度之差K,再令一个指针从长链表开始先走K步,令另一个指针从短链表头开始, // 两链表一起走,相遇点就为入口点 // //经过调试发现 还必须在返回之前将链表复原,不然会出现丢失链表结点的情况,应对函数进行修改 //在实现函数功能之后将环复原 // if (pHead)//判空 { SListNode *tmp = IsRing(pHead); if (tmp)//判有环 { SListNode *cur = pHead; SListNode *NewNode = tmp->next; SListNode*tmp_fail = tmp;//将截断处保存 SListNode*tmp_head = NewNode; tmp->next = NULL;//将环从tmp处截断 int c1 = _LengthNode(cur); int c2 = _LengthNode(NewNode); int minus = _LengthNode(cur) - _LengthNode(NewNode); if (minus > 0) { while (minus--) { cur = cur->next; } } else { int tmp = -minus; while (tmp--) { NewNode = NewNode->next; } } while (NewNode!=cur) { NewNode = NewNode->next; cur = cur->next; } tmp_fail->next = tmp_head;//将原环修复 return cur; } return NULL; } return NULL;}
0 0
- 笔试,面试,C/C++,判断单链表是否带环?若带环,求环长度,求环入口点(两种方法)
- 判断单链表是否带环?若带环,求环的长度?求环的入口点?(C语言)
- 判断单链表是否带环,若带环,求环的长度,求环的入口点
- 判断单链表是否带环? 若带环, 求环的长度? 求环的入口点?
- 判断单链表是否带环? 若带环, 求环的长度? 求环的入口点?
- 判断单链表是否带环?若带环,求环的长度?求环的入口点?
- 判断单链表是否带环?若带环,求环的长度?求环的入口点?
- 判断单链表是否带环?若带环,求环的长度,求环的入口点
- 判断链表是否带环?若带环求环的长度?求环的入口点?
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- -判断链表是否带环?若带环求环的长度?若带环求环的入口点
- 剑指offer--判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 链表--判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断链表是否带环,若带环求环的长度,若带环求环的入口点
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- <笔试><面试>单链表相关(1)从尾到头打印链表、删除一个无头链表的非尾结点
- 笔试面试单链表相关(2)在任意位置前插入结点、逆置链表
- 笔试面试,单链表相关(3)遍历一次找中间结点、倒数第K个结点
- C/C++,数据结构单链表实现约瑟夫环
- 笔试,面试,C/C++,数据结构单链表排序(改进冒泡排序)
- 笔试,面试,C/C++,判断单链表是否带环?若带环,求环长度,求环入口点(两种方法)
- <笔试><面试>C/C++单链表相关(4)判断两链表是否相交,求交点(链表不带环/可能带环)
- <笔试><面试>C/C++单链表(最综合)最全工程从建立到相关函数实现
- C++,笔试面试,使用C++编程,实现万年历
- C/C++,笔试面试,多种方法求100以内的所有素数
- 数据库范式例子说明
- 两数的最大公约数、最小公倍数
- 两个数字交换(不使用临时变量)
- 编写程序将2000年以内的平年闰年分开并分别计算个数