C/C++之有环链表的环起点

如何判断一个链表是否有环,并求出环的起始点。
第一种解法set,set容器默认去重,当循环遍历查询当前节点是否保存到set容器中,如果存在就直接返回直接输出当前节点的数据值,如果不存在则将当前节点直接插入set容器中

#include <iostream>
#include<set>
using namespace std ;
struct node
{
	int data ;
	struct node *next ;
};
typedef struct node *PLIST;
typedef struct node NODE;
PLIST createList_link()
{
	PLIST head=new struct node;
	head->next=NULL;
	return head ;
}
void insertTail(PLIST llist,int x)
{
	PLIST tail=llist->next;
	PLIST temp=new struct node;
	temp->data=x;
	temp->next=NULL;
	if(tail==NULL)
	{
		llist->next=temp;
		return;
	}
	else
	{
		while(tail->next!=NULL)
		{
			tail=tail->next;
		}
	}
	tail->next=temp;
}
void finishCircle(PLIST head,int num)
{
	PLIST p=head->next,q,r;
	while(p!=NULL)
	{
		if(p->data==num)
		{
			q=p;
			break;
		}
		p=p->next;
	}
	while(p->next!=NULL)
	{
		p=p->next;
	}
	p->next=q;
}
void printList_link(PLIST head)
{
    for(PLIST p=head->next;p!=NULL;p=p->next){
        cout<<p->data<<" ";
    }
    cout<<endl;
}
int main()
{
	//begin 生成链表 
	int arr[]={3,324,34,23,12,45,34};
	PLIST head=createList_link();
	for(int i=0;i<7;i++)
	{
		insertTail(head,arr[i]);
	}
	finishCircle(head,34);
//	printList_link(head);
	//end 
	set<PLIST> s;
	PLIST p=head->next;
	while(p!=NULL)
	{
		if(s.count(p)==0)
			s.insert(p);
		else
			break;
		p=p->next;	
	}  
	cout<<p->data;	
	return 0;
} 

第二种解法,双指针法,一个指针的移动速度为1,另一个指针的移动速度为2,设链表无环长度为x,环链表长度为y,设两指针在m处相遇,则有方程x+k1y+m=2(x+m+k2y),m=(2*k2-k1)y-x,其实说明当两个指针相遇时,距离环起点长度只有x,恰好等于无环长度的距离

#include <iostream>
#include<set>
using namespace std ;
struct node
{
	int data ;
	struct node *next ;
};
typedef struct node *PLIST;
typedef struct node NODE;
PLIST createList_link()
{
	PLIST head=new struct node;
	head->next=NULL;
	return head ;
}
void insertTail(PLIST llist,int x)
{
	PLIST tail=llist->next;
	PLIST temp=new struct node;
	temp->data=x;
	temp->next=NULL;
	if(tail==NULL)
	{
		llist->next=temp;
		return;
	}
	else
	{
		while(tail->next!=NULL)
		{
			tail=tail->next;
		}
	}
	tail->next=temp;
}
void finishCircle(PLIST head,int num)
{
	PLIST p=head->next,q,r;
	while(p!=NULL)
	{
		if(p->data==num)
		{
			q=p;
			break;
		}
		p=p->next;
	}
	while(p->next!=NULL)
	{
		p=p->next;
	}
	p->next=q;
}
void printList_link(PLIST head)
{
    for(PLIST p=head->next;p!=NULL;p=p->next){
        cout<<p->data<<" ";
    }
    cout<<endl;
}
int main()
{
	//begin 生成链表 
	int arr[]={3,324,34,23,12,45,34};
	PLIST head=createList_link();
	for(int i=0;i<7;i++)
	{
		insertTail(head,arr[i]);
	}
	finishCircle(head,34);
//	printList_link(head);
	//end 
	PLIST n1,n2,n3;
	n1=head->next;
	n2=head->next;
	n3=head->next;
	n1=n1->next;
	n2=n2->next->next;
	while(n1!=n2)
	{
		n1=n1->next;
		n2=n2->next->next;
	}
	while(n3!=n1)
	{
		n3=n3->next;
		n1=n1->next;
	 } 
	cout<<n3->data;
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值