单链表面试题系列之链表相交问题

来源:互联网 发布:watermark软件 编辑:程序博客网 时间:2024/05/17 21:53

***单链表面试题系列之链表相交问题***



// 链表相交示意图



/* 判断链表是否相交的问题;(前提两个链表都不带环) 我这里有两种思路:

方法一: 联系前面讲的带环链表问题,我们可以将链表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;}elseprintf("没有相交点\n");}int main(){test();system("pause");return 0;}

未完待续!



1 0
原创粉丝点击