单链表面试题系列之链表相交问题
2016-06-13 11:05
459 查看
***单链表面试题系列之链表相交问题***
// 链表相交示意图/* 判断链表是否相交的问题;(前提两个链表都不带环) 我这里有两种思路:
方法一: 联系前面讲的带环链表问题,我们可以将链表2 链接到链表1的尾部,如果两个链表相交,则必然会带环;这样的话我们就可以通过前面讲的带环链表找入口点的方法去做了;
这里给出链表带环问题的链接:http://blog.csdn.net/bitboss/article/details/51648030
方法二: 简单的来想的话,其实如果两个链表相交的话,那么指向最后一个结点的指针必然相同,那么只需要比较两个链表的最后一个结点的地址了!至于找到相交点的问题,那就需要知道两个链表的长度,然后求出链表长度差 n;然后定义两个指针分别从两个链表的头部开始走,长的那个链表先走过 n 步后,短的链表头部指针再开始走,当两个指针相同的时候就找到了相交点! 同样hash方法也可以做;
有其他方法的同学可以告诉我,让我也学习学习!
*/
//这里只实现方法2:
#include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int DataType; typedef struct LinkNode { DataType data; struct LinkNode* next; }LinkNode,*pLinkNode;//结点结构体 typedef struct LinkList { LinkNode* pHead;//头结点指针 LinkNode* pback; }LinkList ,*pLinkList;//链表 void PushBack(pLinkList pList,DataType x) { pLinkNode cur = NULL; pLinkNode pvr = NULL; pLinkNode newNode = (pLinkNode)malloc(sizeof(LinkNode )); if(newNode == NULL) { printf("out of memory\n"); exit(0); } assert(pList); cur = pList ->pback ; newNode ->data = x; newNode ->next = NULL; if(cur == NULL) { pList->pHead = newNode; pList->pback = newNode ; } else { cur->next = newNode ; pList->pback = newNode ; } }//尾插 void InitLinkList(pLinkList pList) { assert(pList); pList->pHead = NULL; pList->pback = pList->pHead ; }//初始化列表 //构造相交链表 void Makeintersect(pLinkList pList1, pLinkList pList2) { //所谓构造相交链表,就是让一个链表的最后又指向另一个链表的某个节点; pLinkNode cur = NULL; pLinkNode pvr = NULL; assert(pList1); assert(pList2); cur = pList2->pHead ; //找到第二个结点的尾部,然后让最后一个结点指向第一个节点的某一个结点; while(cur) { pvr = cur; cur = cur->next ; } pvr->next = pList1 ->pHead;//指向链表1的任意结点,由你自己决定测试; // pvr->next = pList1 ->pHead->next 也可以; } //判断两个链表是否相交(都不带环); int Judege_Cross(pLinkList pList1,pLinkList pList2) { pLinkNode ptr1 = NULL; pLinkNode ptr2 = NULL; pLinkNode tmp1 = NULL; pLinkNode tmp2 = NULL; assert(pList1); assert(pList2); ptr1 = pList1 ->pHead ; ptr2 = pList2 ->pHead ; while(ptr1)//找到指向链表1最后一个结点的指针 { tmp1 = ptr1; ptr1 = ptr1->next ; } while(ptr2)//找到指向链表2最后一个结点的指针 { tmp2 = ptr2; ptr2 = ptr2->next ; } if( tmp1 == tmp2)//比较两个链表最后一个结点是否相同 return 1;//相同即有交点返回1; return 0;//否则无交点返回0; } //找链表的交点 pLinkNode Find_Cross_Node(pLinkList plist1,pLinkList plist2) { pLinkNode ptr1 = NULL; pLinkNode ptr2 = NULL; pLinkNode tmp1 = NULL; pLinkNode tmp2 = NULL; int len1 = 0;//链表1的长度 int len2 = 0;//链表2的长度 int n = 0;//链表的长度差 assert(plist1); assert(plist2); ptr1 = plist1->pHead ; ptr2 = plist2->pHead ; tmp1 = ptr1; tmp2 = ptr2; while(ptr1)//求链表1的长度 { len1++; ptr1 = ptr1->next ; } while(ptr2)//求链表2的长度 { len2++; ptr2 = ptr2->next ; } if(len1 >= len2)//如果链表1长,则tmp1先走n步 { n = len1 -len2; while(n--) { tmp1 = tmp1->next ; } } else//否则tmp2先走n步 { n = len2 -len1; while(n--) { tmp2 = tmp2->next ; } } while(tmp1 != tmp2)//找相同的指针 { tmp1 = tmp1->next ; tmp2 = tmp2->next ; } return tmp1;//找到相交点返回 } void test() { //自己设计两个链表 LinkList List1 ; LinkList List2 ; pLinkNode tmp = NULL; int ret = 0; InitLinkList(&List1); InitLinkList(&List2); PushBack(&List1, 1); PushBack(&List1, 2); PushBack(&List1, 3); PushBack(&List1, 4); PushBack(&List1, 5); PushBack(&List2, 6); PushBack(&List2, 7); PushBack(&List2, 8); Makeintersect(&List1 ,&List2 );//构造相交链表,测试没有相交时可以屏蔽掉这句代码; ret = Judege_Cross(&List1,&List2);//判断是否相交; if(ret == 1)//如果相交,找出相交点; { tmp = Find_Cross_Node(&List1,&List2); printf("找到的相交点为:%d\n",tmp->data );//输出相交结点的data; } else printf("没有相交点\n"); } int main() { test(); system("pause"); return 0; }
未完待续!
相关文章推荐
- 一个关于if else容易迷惑的问题
- [C/C++]反转链表
- C#实现基于链表的内存记事本实例
- 一道sql面试题附答案
- C#模拟链表数据结构的实例解析
- C# 超高面试题收集整理
- C语言实现带头结点的链表的创建、查找、插入、删除操作
- C++利用静态成员或类模板构建链表的方法讲解
- C++实现简单的学生管理系统
- 人人网javascript面试题 可以提前实现下
- Linux内核链表实现过程
- C++链表倒序实现方法
- C#通过链表实现队列的方法
- PHP中设置一个严格30分钟过期Session面试题的4种答案
- Node.js环境下JavaScript实现单链表与双链表结构
- C#实现的简单链表类实例
- 找出链表倒数第n个节点元素的二个方法
- 据说是雅虎的一份PHP面试题附答案
- php牛逼的面试题分享
- 一套比较完整的javascript面试题(部分答案)