//(1)给出算法的基本设计思想
// 1.设置快慢指针,其中快的走两个结点慢的走一个结点
// 2.如果快指针为空则就是无环链表,若快指针在某个结点上等于慢指针则为有环结点
// 3.如果是有环节点可以在表头创建节点p,移动p和慢指针当p==slow后,即为环的起点
// 具体:设表头到环的距离为L,设快指针与慢指针相遇的结点为x,从两指针相遇的结点到起点为y,设一圈的距离为R
// 则慢指针一共移动了L+x个结点,快指针则移动了2(L+x)个结点,快指针比慢指针多走了n圈
// 则他们的具体有等式 2(L + x) = L + x + nR
// 化简得 L = nR - x
// 提出一个R L = (n - 1)R + (R-x)
// (n-1)R可以当做0,(R+x)=y L = y
// 所以移动y次后p和slow相遇就是起点
//(2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释
typedef struct LNode
{
int data;
struct LNode* next;
}LNode,*LinkList;
bool InitList(LinkList * L)//初始化
{
(*L) = (LNode*)malloc(sizeof(LNode));
if ((*L) == NULL)
return false;
(*L)->next = NULL;
return true;
}
bool InsertList(LinkList* L)
{
LNode* p = (*L);//尾指针
if (p == NULL)
return false;
int i = 0;
scanf("%d", &i);
while (i != 9999)
{
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return true;
s->data = i;
s->next = p->next;
p->next = s;
p = s;
scanf("%d", &i);
}
//p->next = NULL;//不带环链表
LNode* q = (*L);
for (i = 0; i < 4; i++)
q = q->next;
p->next = q;//假设链表带环,并且假设起始地点为q结点
return true;
}
bool Surround(LinkList L)//判断是否带环如果带环找到环的起点
{
LNode* fast = L;
LNode* slow = L;
while (fast->next != NULL && fast->next->next != NULL)
{
fast = fast->next->next;//快指针走两步
slow = slow->next;//慢指针走一步
if (fast == slow)
break;
}
if (fast->next == NULL || fast->next->next == NULL)//不带环的情况
{
printf("不带环\n");
return false;
}
//带环的情况
LNode* p = L;
if (p == NULL)
return false;
while (p != slow)
{
p = p->next;
slow = slow->next;
}
if (p == slow)
{
printf("环的入口结点为\n");
printf("%d \n", p->data);
}
return true;
}
bool PrintList(LinkList L)
{
LNode* p = L->next;
if (p == NULL)
return false;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
return true;
}
int main()
{
LinkList L;//指向链表的指针
InitList(&L);//初始化
InsertList(&L);//插入
Surround(L);//判断是否带环
//PrintList(L);//测试
return 0;
}
//(3)说明你所设计算法的时间复杂度和空间复杂度
//时间复杂度O(n)
//空间复杂度O(1)