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

***单链表面试题系列之链表相交问题***// 链表相交示意图/* 判断链表是否相交的问题;(前提两个链表都不带环) 我这里有两种思路:方法一: 联系前面讲的带环链表问题,我们可以将链表2 链接到链表1的尾部,如果两个链表相交,则必然会带环;这样的话我们就可以通过前面讲的带环链表找入口点的方法去做了;这里给出链表带
摘要由CSDN通过智能技术生成

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



// 链表相交示意图



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

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

未完待续!



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值