我有单链表。假设单个链表的最后一个节点不为空并指向列表中的某个任意节点而不是NULL(这意味着它不是'\0'
)。因此链接列表循环但不指向第一个节点。我想找到链表的最后一个节点。你能建议我解决这个问题的算法吗?
答案 0 :(得分:4)
我认为这就是你所需要的。
将head
初始化为两个指针。
int *temp1 = head, *temp2 = head;
将一个指针增加两倍于另一个指针。如果链表有循环,则两个指针将在循环中的某个点处相遇。我们使用temp2
来存储此会合点节点。
while (temp1 != temp2)
{
temp1 = temp1->next;
temp1 = temp1->next;
temp2 = temp2->next;
}
迭代指针(temp1
)以圈出循环并计算其长度。
temp1 = temp1->next; // At this point temp1 is the node of the meeting point
loop_length = 0;
while (temp1 != temp2)
{
temp1 = temp1->next;
loop_length++;
}
将指针temp1
初始化为head
并提前loop_length
步。
temp1 = head;
while (i < loop_length)
{
temp1 = temp1->next;
i++;
}
将另一个指针temp3
初始化为head
,然后同时迭代temp1
和temp3
,直到它们相遇为止。循环终止后,两者都将在循环的起始点相遇。
temp3 = head;
while (temp1 != temp3)
{
temp1 = temp1->next;
temp3 = temp3->next;
}
现在,您可以从temp4
开始使用另一个指针temp3
并遍历列表,直到temp4->next
和temp3
相遇。
temp4 = temp3;
while (temp4->next != temp3)
{
temp4 = temp4->next;
}
现在temp4
将包含列表的结尾。
答案 1 :(得分:1)
据我所知,你有这样的东西,整数只是为了命名节点的标签:
1 -> 2 -> 3 -> 4 -> 2
我想你问的是如何检测到节点4指向列表中较早出现的内容。我认为根据你的定义,4将是列表的结尾。请验证!
在这种情况下,最简单的方法是开始一个开始并逐步浏览列表,每次将节点标记为已访问(如果您可以为此目的添加数据),或保持设置结构访问节点。在每个步骤中,您可以查看下一个节点是否在访问集中。如果是,你找到了最后一个节点,如果不是,你把它放在集合中并继续。
因此,对于这些数据我们得到了
current next visited Comment
------- ---- ------- -------
1 2 {1}
2 3 {1, 2}
3 4 {1, 2, 3}
4 2 Stop, 2 is in visited, so 4 is the "last" node.
答案 2 :(得分:0)
如果我理解你的问题。你有一个链表,其中最后一个指针指向一个前一个条目,如此
This Next Etc.
1 2 xxxx
2 3 xxxxx
3 4
4 5
6 3
因此,您需要保留已访问过的条目表。当您找到表中已存在的“下一个”值时,则当前条目是列表中的最后一个条目。
即
do forever
visited[This] = "Y";
move to Next
if visited[Next] == "Y"
exit loop
next;