链表面试题之带环问题

    面试题一:判断链表是否带环,如果链表带环则返回相遇点

     pLinkNode Check_Cycle(pLinkList plist); 
     首先先给出代码的结构实现:
      
typedef int DataType;

typedef struct LinkNode
{
	DataType data;
	struct LinkNode *next;
}LinkNode,*pLinkNode;    

typedef struct LinkList
{
	LinkNode *phead;
}LinkList,*pLinkList; 



     看到这道问题如何去分析呢?我们可以类比运动员在操场上赛跑的实例,如果一个运动员跑的快另一个跑的慢,那仫这两个运动员必然会在操场相遇;假设我们链表中的环就是操场,存在两个指针,一个快指针,一个慢指针,如果链表带环那仫这两个指针必定会在操场上的某一点相遇,这就判断了链表是否带环的问题啦!在这里就用到了我们之前提到的快慢指针的问题了,代码实现如下:
           
pLinkNode Check_Cycle(pLinkList plist)   //判断链表是否带环,若带环则返回相遇点
{
	pLinkNode fast=NULL;
	pLinkNode slow=NULL;
	assert(plist);
	fast=plist->phead;
	slow=plist->phead;
	while(fast && fast->next)
	{
		fast=fast->next->next;
		slow=slow->next;
		if(fast == slow)
		{
			return fast;
		}
	}
	return NULL;
}


        面试题二.若链表带环则求出环的长度和环的入口点

         int Get_CircleLength(pLinkNode meet);        //求带环链表环的长度
         pLinkNode GetCircle_EntryNode(pLinkList plist,pLinkNode meet);     //求带环链表环的入口点
         
        如何求带环链表的长度呢?在上述判断链表是否带环的实现中我们找到了两个指针的相遇点,当然如果我们从相遇点遍历链表,每遍历一次count就自加一次当再次遍历到相遇点时也就统计出了带环链表的长度;代码实现如下
        
int Get_CircleLength(pLinkNode meet)     //求环的长度
{
	int count=1;
	pLinkNode cur=meet;
	pLinkNode pmeet=meet;
	while(cur->next != pmeet)
	{
		count++;
		cur=cur->next;
	}
	return count;
}



        如何求带环链表的入口点呢?请看下列推导过程:
        
         由上述推导的等式x=n*L-y, 可以知道要求出环的入口点必须设置两个指针,一个指针指向链表的第一个结点,一个指针指向环内的相遇点,同时开始遍历链表,那仫经历过n圈遍历后两个指针必然指向同一个结点,这个结点就是环的入口点,详细分析可见上图,代码实现如下:
         
pLinkNode GetCircle_EntryNode(pLinkList plist,pLinkNode meet)   //获取环的入口点
{
	pLinkNode front=plist->phead;
	pLinkNode back=meet;
	assert(plist);
	while(front != back)
	{
		front=front->next;
		back=back->next;
	}
	return front;
}



      
        测试结果如下:
         
        
void text7()
{
	int ptr=0;
	pLinkNode ret=NULL;
	pLinkNode meet=NULL;
	LinkList plist;
	Init_LinkList(&plist);
	Push_back(&plist,1);
	Push_back(&plist,2);
	Push_back(&plist,3);
	Push_back(&plist,4);
	Push_back(&plist,5);
	ret=Find_NUM(&plist,5);  //构造环
	ret->next=Find_NUM(&plist,3);

	meet=Check_Cycle(&plist);
	if(meet != NULL)
	{
		printf("带环链表的相遇结点为:%d\n",meet->data);
		ptr=Get_CircleLength(meet);
		printf("带环链表的环的长度为:%d\n",ptr);
		ret=GetCircle_EntryNode(&plist,meet);
		printf("带环链表的环的入口点为:%d\n",ret->data);
	}
	Free_LinkList(&plist);
}

int main()
{
	text7();
	system("pause");
	return 0;
}


         本文如有缺陷请读者指出,共同进步!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值