码迷,mamicode.com
首页 > 编程语言 > 详细

c/c++单链表面试题—链表带环问题

时间:2016-03-17 02:14:31      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:链表带环问题

1、判断一个单链表是否带环

思路解析:

判断一个单链表是不是带环,就看在遍历单链表的时候能不能遍历完成,如果带环的话会陷入死循环程序一直无法结束,但是这种判断方法在程序的实现是不可能的。所以转换一种思路,利用两个遍历速度不同的指针遍历,如果存在环的话,那么快指针迟早会追上慢指针。通过这个判断程序实现起来是比较简单可行的。

单链表的结构体及其类的定义

struct Node
{
public:
	Node(const DataType& d)
		:_data(d)
		,_next(NULL)
	{}
public:
	DataType _data;
	Node* _next;
};

class List
{
public:
	List()
		:_head(NULL)
		,_tail(NULL)
	{}

	~List()
	{
		Node* cur = _head;
		while (cur && cur!=_tail)
		{
			Node* del = cur;
			cur = cur->_next;
			delete del;
		}
		delete _tail;//因为如果存在环的话尾指针的next域不为空会使
		_head = NULL;//环入口点析构两次,导致程序崩溃
		_tail = NULL;
	}
private:
	Node* _head;
	Node* _tail;
};

判断单链表是不是存在环

Node*  List::CheckCycle()
{
	Node* slow = _head;//慢指针
	Node* fast = _head;//快指针
	while (fast && fast->_next)
	{
		slow = slow->_next;
		fast = fast->_next->_next;
		if (fast == slow)
		{
			return slow;//有环返回相遇的节点
		}
	}
	return NULL;//无环
}

2、求取环的长度

思路分析:

在上面已经找到了快慢指针的相遇节点,我们可以通过在相遇的节点处重新遍历,并且引入一个计数器,直到再次到达相遇节点。

int  List::GetCircleLength(Node* meet)
{
	Node* start = meet;
	Node* end = meet;
	int count = 0;//计数器
	do
	{
		start = start->_next;
		count++;
	} while (start != end);
	return count;
}

3、找到环的入口点

1)一个指针从相遇的节点开始遍历,另外一个从头开始遍历直到两个指针相遇,即是入口点。

Node*  List::GetCycleEntryNode(Node* meetNode)
{
	Node* start = _head;
	Node* end = meetNode;
	while (start != end)
	{
		start = start->_next;
		end = end->_next;
	}

	return start;
}

2)将环在快慢指针相遇节点的下一个节点拆分成两个链表,使得这个问题既可转化为链表的相交问题,链表的交点即是环入口点。

Node*  List::GetCycleEntryNode(Node* meetNode)
{
	Node *l1 = _head;
	Node *l2 = meetNode->_next;//从相遇节点的下一个节点开始
	meetNode->_next = NULL;//将两条单链表的尾节点的_next域赋为空
	Node *Enter = GetCrossNode(l1, l2);//将单链表拆分成两条并找交点
	meetNode->_next = l2;//将原始的单链表恢复
	return Enter;
}

c/c++单链表面试题—链表带环问题

标签:链表带环问题

原文地址:http://10788311.blog.51cto.com/10778311/1751887

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!