您的位置:首页 > 编程语言 > C语言/C++

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

2016-05-29 17:22 369 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: