《C语言实现链表相交、带环问题》
来源:互联网 发布:远程火箭炮知乎 编辑:程序博客网 时间:2024/05/17 10:05
例题:
//1.判断单链表是否带环?若带环,求环的长度?求环的入口点?//2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)//3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】//4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,//还有一个random指针指向这个链表中的一个随机节点或者NULL,//现在要求实现复制这个链表,返回复制后的新链表。////ps: 复杂链表的结构 //struct ComplexNode//{// int _data; // 数据 // struct ComplexNode * _next; // 指向下一个节点的指针 // struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空) //};
基本函数:
#include<stdio.h>#include<stdlib.h>#include<assert.h>#include<math.h>typedef int DataType;//节点中数据类型typedef struct ListNode//节点数据结构{ DataType data; struct ListNode *next;} ListNode;ListNode *Find(ListNode *plist,DataType x)//查找函数,返回查找到节点的地址{ ListNode *cur = plist; while (cur) { if ((cur->data) == x) { return cur; } cur = cur->next; } return cur;}ListNode *BuyNode(DataType x)//产生一个节点并把节点中的数据置数,返回节点地址{ ListNode *plist = (ListNode *)malloc(sizeof(ListNode)); if (plist != NULL) { plist->data = x; plist->next = NULL; return plist; } return NULL;}void PrintList(ListNode *plist)//打印单链表{ assert(plist != NULL); while (plist) { printf("%d->",plist->data); plist = plist->next; } printf("NULL\n");}void PushBuck(ListNode **pplist,DataType x)//在函数尾部插入节点{ ListNode *cur = NULL; assert(pplist); cur = *pplist; if (*pplist == NULL) { *pplist = BuyNode(x); return; } while ((cur->next) != NULL) { cur = cur->next; } cur->next = BuyNode(x);}
1.判断单链表是否带环?若带环,求环的长度?求环的入口点?
思路:
ListNode *IsCycle(ListNode *plist)//判断是否带环{ ListNode *fast = plist; ListNode *slow = plist; assert(plist); while ((fast != NULL) && (fast->next != NULL)) { fast = fast->next->next; slow = slow->next; if (fast == slow) return fast; } return NULL;}int GetCycleLen(ListNode *meetnode)//求环的长度{ ListNode *cur = NULL; int count = 1; assert(meetnode); cur = meetnode->next; while (cur != meetnode) { cur = cur->next; count++; } return count;}ListNode *GetCycleEnter(ListNode *plist, ListNode *meetnode)//求环的入口点{ assert(plist); assert(meetnode); while (plist != meetnode) { plist = plist->next; meetnode = meetnode->next; } return plist;}void Test(){ ListNode *plist = NULL; ListNode *tmp1 = NULL; ListNode *tmp2 = NULL; ListNode *tmp = NULL; PushBuck(&plist, 1); PushBuck(&plist, 2); PushBuck(&plist, 3); PushBuck(&plist, 4); PushBuck(&plist, 5); PushBuck(&plist, 6); PushBuck(&plist, 7); tmp1 = Find(plist, 3); tmp2 = Find(plist, 7); tmp2->next = tmp1; tmp = IsCycle(plist); if (tmp == NULL) printf("不带环!\n"); else { printf("带环!\n"); printf("环的长度为:%d\n",GetCycleLen(tmp)); printf("环的入口点为:%d\n",GetCycleEnter(plist,tmp)->data); }}
结果:
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
bool CheckIsMeet(ListNode *plist1,ListNode *plist2)//判断是否相交{ assert(plist1); assert(plist2); while (plist1->next != NULL) { plist1 = plist1->next; } while (plist2->next != NULL) { plist2 = plist2->next; } if (plist1 == plist2) { return true; } else { return false; }}ListNode *AnswerMeetNode(ListNode *plist1,ListNode *plist2)//若相交,求交点{ int count1 = 0; int count2 = 0; int count = 0; ListNode *cur1 = plist1; ListNode *cur2 = plist2; while (cur1 != NULL) { count1++; cur1 = cur1->next; } while (cur2 != NULL) { count2++; cur2 = cur2->next; } count = count1 - count2; if (count > 0) { while (count--) { plist1 = plist1->next; } } else { count = -count; while (count--) { plist2 = plist2->next; } } while (plist1 != plist2) { plist1 = plist1->next; plist2 = plist2->next; } return plist1;}void Test1(){ ListNode *plist1 = NULL; ListNode *plist2 = NULL; ListNode *tmp1 = NULL; ListNode *tmp2 = NULL; bool flag = true; PushBuck(&plist1, 1); PushBuck(&plist1, 3); PushBuck(&plist1, 5); PushBuck(&plist1, 7); PushBuck(&plist1, 8); PushBuck(&plist1, 9); PushBuck(&plist1, 10); PushBuck(&plist2, 2); PushBuck(&plist2, 4); PushBuck(&plist2, 6); tmp1 = Find(plist2, 6); tmp2 = Find(plist1, 7); tmp1->next = tmp2; flag = CheckIsMeet(plist1, plist2); if (flag) { printf("相交!\n"); printf("交点为:%d\n",AnswerMeetNode(plist1,plist2)->data); } else { printf("不想交!\n"); }}
结果:
3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
思路:
RetuenNoode CheckIsMeetTop(ListNode *plist1, ListNode *plist2)//判断两个链表是否相交,若相交,求交点.(假设链表可能带环)【升级版】{ ListNode *tmp1 = NULL; ListNode *tmp2 = NULL; RetuenNoode ret = { 0, NULL, NULL }; assert(plist1); assert(plist2); tmp1 = IsCycle(plist1); tmp2 = IsCycle(plist2); if ((tmp1 == NULL) && (tmp2 == NULL)) { //都不带环 tmp1 = plist1; tmp2 = plist2; while (tmp1->next != NULL) { tmp1 = tmp1->next; } while (tmp2->next != NULL) { tmp2 = tmp2->next; } if (tmp1 == tmp2) { //相交 ret.plist1 = AnswerMeetNode(plist1, plist2); ret.flag = 1; return ret; } else { //不相交 ret.flag = 1; return ret; } } else if ((tmp1 != NULL) && (tmp2 != NULL)) { //两者都带环 ListNode *tmp = tmp1->next; while ((tmp != tmp2) && (tmp != tmp1)) { tmp = tmp->next; } if (tmp == tmp2) { //相交 tmp1 = GetCycleEnter(plist1,tmp1); tmp2 = GetCycleEnter(plist2,tmp2); if (tmp1 == tmp2) { //交点在链上 int count1 = 0; int count2 = 0; int count = 0; ListNode *cur1 = plist1; ListNode *cur2 = plist2; while (cur1 != tmp1) { count1++; cur1 = cur1->next; } while (cur2 != tmp1) { count2++; cur2 = cur2->next; } count = count1 - count2; if (count > 0) { while (count--) { plist1 = plist1->next; } } else { count = -count; while (count--) { plist2 = plist2->next; } } while (plist1 != plist2) { plist1 = plist1->next; plist2 = plist2->next; } ret.plist1 = plist1; ret.flag = 3; return ret; } else { //两个交点都在环上 ret.plist1 = tmp1; ret.plist2 = tmp2; ret.flag = 3; return ret; } } else { //不相交 ret.flag = 3; return ret; } } else { //一个带环,一个不带环。必不相交 ret.flag = 2; return ret; }}void Test2(){ RetuenNoode ret = {0,NULL,NULL}; ListNode *plist1 = NULL; ListNode *plist2 = NULL; ListNode *tmp1 = NULL; ListNode *tmp2 = NULL; PushBuck(&plist1, 1); PushBuck(&plist1, 3); PushBuck(&plist1, 5); PushBuck(&plist1, 7); PushBuck(&plist1, 8); PushBuck(&plist1, 9); PushBuck(&plist1, 10); PushBuck(&plist2, 0); PushBuck(&plist2, 2); PushBuck(&plist2, 4); PushBuck(&plist2, 6); tmp1 = Find(plist1, 10);//第三类相交 b> 2> tmp2 = Find(plist1, 7); tmp1->next = tmp2; tmp1 = Find(plist1, 9); tmp2 = Find(plist2, 6); tmp2->next = tmp1; //tmp1 = Find(plist1, 10);//第三类相交 b> 1> //tmp2 = Find(plist1, 7); //tmp1->next = tmp2; //tmp1 = Find(plist1, 5); //tmp2 = Find(plist2, 6); //tmp2->next = tmp1; //tmp1 = Find(plist2, 2);//第三类不相交 //tmp2 = Find(plist2, 6); //tmp2->next = tmp1; //tmp1 = Find(plist1, 7); //tmp2 = Find(plist1, 10); //tmp2->next = tmp1; //tmp1 = Find(plist1, 7);//第二类不相交 //tmp2 = Find(plist1, 10); //tmp2->next = tmp1; //第一类不相交 //tmp1 = Find(plist2, 6);//第一类相交 //tmp2 = Find(plist1, 7); //tmp1->next = tmp2; ret = CheckIsMeetTop(plist1,plist2); if (ret.flag == 3) { if ((ret.plist1) && (ret.plist2)) { printf(" 第三类 -> b> -> 2> :\nMeetNode1:%d\nMeetNode2:%d\n", ret.plist1->data, ret.plist2->data); } else if (ret.plist1) { printf("第三类 -> b> -> 1> :\nMeetNode:%d\n", ret.plist1->data); } else { printf("第三类不相交!\n"); } } else if (ret.flag == 1) { if (ret.plist1) { printf("第一类相交:\nMeetNode:%d\n", ret.plist1->data); } else { printf("第一类不相交!\n"); } } else { printf("第二类不相交!\n"); }}int main(){ //Test(); //Test1(); Test2(); return 0;}
结果:
4.复杂链表的复制。
思路:
#include<stdio.h>#include<stdlib.h>#include<assert.h>typedef int DataType;typedef struct ComplexNode{ DataType data;//数据 struct ComplexNode *next;//指向下一个节点 struct ComplexNode *random;//指向随机节点} ComplexNode;ComplexNode *BuyNode(DataType x)//产生新节点{ ComplexNode *tmp = (ComplexNode *)malloc(sizeof(ComplexNode)); tmp->data = x; tmp->next = NULL; tmp->random = NULL; return tmp;}void PushBack(ComplexNode **pplist,DataType x)//尾插函数{ ComplexNode *cur = NULL; assert(pplist); cur = *pplist; if (*pplist == NULL) { *pplist = BuyNode(x); } else { while (cur->next) { cur = cur->next; } cur->next = BuyNode(x); }}ComplexNode *FindComplexNode(ComplexNode *plist,DataType x)//查找函数{ if (plist == NULL) { return NULL; } else { while (plist) { if (plist->data == x) return plist; plist = plist->next; } return NULL; }}ComplexNode *LineComplexNode(ComplexNode *plist)//第一步、产生节点并连接节点{ ComplexNode *phead = plist; ComplexNode *tmp = NULL; ComplexNode *ret = NULL; assert(plist); while (plist) { ret = plist->next; tmp = BuyNode(plist->data); tmp->next = plist->next; plist->next = tmp; tmp->random = NULL; plist = ret; } return phead;}void RandomEvaluate(ComplexNode *plist)//第二步、random指针赋值{ assert(plist); while (plist) { if (plist->random == NULL) { plist->next->random = NULL; } else { plist->next->random = plist->random->next; } plist = plist->next->next; }}void PrintComplexNode(ComplexNode *plist)//打印节点{ while (plist) { printf("%d->",plist->data); plist = plist->next; } printf("NULL\n");}void PrintRandom(ComplexNode *plist)//打印random指向的数据{ while (plist) { if (plist->random == NULL) { printf("NULL->"); } else { printf("%d->", plist->random->data); } plist = plist->next; } printf("STOP\n");}ComplexNode *ToPickComplexList(ComplexNode *plist)//摘出复杂链表{ ComplexNode *phead = NULL; ComplexNode *cur = NULL; ComplexNode *tmp = NULL; if (plist == NULL) { return NULL; } while (plist) { cur = plist->next; plist->next = cur->next; if (phead == NULL) phead = tmp = cur; else { tmp->next = cur; tmp = cur; } plist = plist->next; } return phead;}void Test(){ ComplexNode *plist = NULL; ComplexNode *tmp1 = NULL; ComplexNode *tmp2 = NULL; PushBack(&plist, 1); PushBack(&plist, 2); PushBack(&plist, 3); PushBack(&plist, 4); PushBack(&plist, 5); tmp1 = FindComplexNode(plist, 3); plist->random = tmp1; tmp1->random = NULL; tmp1 = FindComplexNode(plist, 2); tmp1->random = plist; tmp1 = FindComplexNode(plist, 4); tmp2 = FindComplexNode(plist, 5); tmp1->random = tmp2; tmp2->random = tmp2;//初始化复杂链表 LineComplexNode(plist);//第一步 RandomEvaluate(plist);//第二步 tmp1 = ToPickComplexList(plist);//摘出链表 PrintComplexNode(plist);//打印原始链表 PrintRandom(plist);//打印原始Random所指向数据 PrintComplexNode(tmp1);//打印新链表 PrintRandom(tmp1);//打印新random所指向数据}int main(){ Test(); return 0;}
结果:
阅读全文
1 0
- 《C语言实现链表相交、带环问题》
- C语言强化(七)链表相交问题_3 判断链表是否带环
- 链表中的带环相交问题
- 判断两个链表是否相交,若相交,求交点。(假设链表不带环)(C语言)
- 带环单链表及链表相交问题的分析及代码实现
- 判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】(C语言)
- 判断两个链表是否相交,若相交,求交点,若带环呢/fork继承问题
- 判断两个链表是否相交,若相交,求交点,考虑带环情况实现代码
- C语言实现单链表面试题--进阶(带环问题)
- 判断带环链表相交的点
- 判断两个链表是否相交,若相交,求交点:1.不带环。2.有可能带环
- 每日一刷——1.判断两个链表是否相交,若相交求交点(链表不带环&带环)2.fork()问题
- C语言实现,无头结点不带环的单向链表的基本操作
- 链表面试题总结----(可能带环相交问题+复杂链表的复制)
- C语言强化(七)链表相交问题_1 判断无环链表相交
- C语言强化(七)链表相交问题_2 找到无环链表相交结点
- C语言强化(七)链表相交问题_4 判断两个有环链表是否相交
- C语言强化(七)链表相交问题_5 找到两个有环链表的相交结点
- Ubuntu 16 释放显存的方法
- layui 弹出层的表单提交
- 欢迎使用CSDN-markdown编辑器
- 为什么中国民居喜欢坐北朝南?
- (4)gsoap方法:软件开发时如何使用webservice接口
- 《C语言实现链表相交、带环问题》
- Javascript 面向对象编程:封装
- linux lsof命令详解
- jsp入門
- 128. Longest Consecutive Sequence(C++)
- linux 开源镜像地址
- React之ref回调函数实现的两种方式
- 多进程多线程TCP服务器以及进程池
- 1-mvn 介绍