一、带环单链表:
带环单链表的概念:当单链表的尾指针指向了链表上任一非尾结点时,即生成了一个带环单链表。
问题一:判断是否带环(通过快慢指针实现判断,注意快指针必须是两步,慢指针必须是一步,否则可能跨过)
问题二:求环的入口点(通过数学思想,方法是使用一指针指向开头,一指针指向环中的相交点,每次各走一步,如此所得相交点即入口点)
问题三:约瑟夫环的决胜者问题
#include<iostream>
using namespace std;
struct Node
{
int _data;
Node* _next = NULL;
};
typedef Node* PList;
Node* CreateNode(int x)
{
Node *temp = new Node;
temp->_data = x;
temp->_next = NULL;
return temp;
}
void push_back(PList &head, int x)
{
Node *tmp = head;
if (head == NULL)
{
head = CreateNode(x);
}
else
{
while (tmp->_next != NULL)
tmp = tmp->_next;
tmp->_next = CreateNode(x);
}
}
Node* Find(PList head, int x)
{
Node* cur = head;
while (cur != NULL)
{
if (cur->_data == x)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
Node* JudgeHasCircle(PList head)
{
//运用快慢指针的思想
Node* fast = head;
Node* slow = head;
Node* temp = head;
while (fast != NULL && fast->_next != NULL)
{
fast = fast->_next->_next;
slow = slow->_next;
if (fast == slow)
break;
}
if (fast != NULL)
{
while (temp != fast)
{
temp = temp->_next;
fast = fast->_next;
}
return temp;
}
else
return NULL;
}
//约瑟夫环游戏
Node* Joe(PList head, int k)
{
//运用快慢指针的思想
Node* fast = head;
Node* slow = head;
Node* temp = head;
Node* dead = NULL;
while (fast != NULL && fast->_next != NULL)
{
fast = fast->_next->_next;
slow = slow->_next;
if (fast == slow)
break;
}
if (fast != NULL)
{
int i = k - 1;
while (temp != temp->_next)
{
i = k - 1;
while (--i > 0)
{
temp = temp->_next;
}
dead = temp->_next;
temp->_next = temp->_next->_next;
temp = temp->_next;
delete dead;
dead = NULL;
}
return temp;
}
else
return NULL;
}
void test1()
{
PList list1;
list1 = NULL;
push_back(list1, 1);
push_back(list1, 2);
push_back(list1, 3);
push_back(list1, 4);
push_back(list1, 5);
push_back(list1, 6);
push_back(list1, 7);
//构建带环单链表
Node *temp = Find(list1, 7);
temp->_next = Find(list1, 4);
//判断是否是带环单链表,以及返回相交结点
temp = JudgeHasCircle(list1);
if (temp == NULL)
printf("无环.\n");
else
{
printf("有环.\n");
cout << temp->_data << endl;
}
}
void test2()
{
PList list1;
list1 = NULL;
push_back(list1, 1);
push_back(list1, 2);
push_back(list1, 3);
push_back(list1, 4);
push_back(list1, 5);
push_back(list1, 6);
push_back(list1, 7);
//构建带环单链表
Node *temp = Find(list1, 7);
temp->_next = Find(list1, 1);
Node *temp1 = Joe(list1, 2);
}
int main()
{
PList list1;
list1 = NULL;
push_back(list1, 1);
push_back(list1, 2);
push_back(list1, 3);
push_back(list1, 4);
push_back(list1, 5);
push_back(list1, 6);
push_back(list1, 7);
//构建无环相交的单链表
PList list2;
return 0;
}
二、单链表相交
单链表相交的概念:即两条单链表存在完全重合的部分,而不是交叉某一点。
问题1:不带环的相交
问题2:带环的相交(注:当为带环单链表相交时,必须是两个单链表都有环,不可能存在一者有环,一者无环的情况。并且,相交之后只可能存在一个环,不可能出现多个环的情况)
问题1的解决:(因为两者相交后,必然有一段一直到尾的部分重合,所以,可以根据尾结点判断重合)
问题2的解决:(同上面求环是否存在的情况,通过两次判断SLst1和SList2,分别找出它们环中的一个结点,再固定其一,另一个绕环走,当出现两结点重合情况,则为相交,其它情况皆为不相交)