您的位置:首页 > 职场人生

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

2016-06-13 11:05 411 查看

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

// 链表相交示意图





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

方法一: 联系前面讲的带环链表问题,我们可以将链表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;
}


未完待续!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  面试题 链表