C++ 如何在单个遍历中找到单个链表的中间节点(如果没有给出链表的长度)
我有一个问题陈述,比如:“如何在一次遍历中找到单个链表的中间节点,问题是我们不知道链表中的节点数?” 我有一个答案,比如“在遍历链表时,获取一个向量并开始推送所有节点的地址,然后递增一个计数器,直到到达链表的末尾”。因此,在最后我们可以得到列表中的节点数,如果偶数(计数器/2)或奇数(计数器/2+计数器%2)给出中间节点数,我们可以得到C++ 如何在单个遍历中找到单个链表的中间节点(如果没有给出链表的长度),c++,linked-list,C++,Linked List,我有一个问题陈述,比如:“如何在一次遍历中找到单个链表的中间节点,问题是我们不知道链表中的节点数?” 我有一个答案,比如“在遍历链表时,获取一个向量并开始推送所有节点的地址,然后递增一个计数器,直到到达链表的末尾”。因此,在最后我们可以得到列表中的节点数,如果偶数(计数器/2)或奇数(计数器/2+计数器%2)给出中间节点数,我们可以得到vectore.at(middleNodeEnumber)指向中间节点” 这很好……但这是存储一个非常大的链表的所有地址的内存浪费!那么我们如何才能有更好的解决方
vectore.at(middleNodeEnumber)
指向中间节点”
这很好……但这是存储一个非常大的链表的所有地址的内存浪费!那么我们如何才能有更好的解决方案呢?您可以使用一个带有两个迭代器的单循环,例如
it1
和it2
,其中您只需在循环的每一次迭代中增加it2
。当it1
重新开始时终止单击列表的结尾。it2
现在将指向列表的中间元素。尝试以下操作:您有两个指针。一个指向中间,另一个指向末尾,这两个指针在开始时都指向列表的开头。每秒钟成功增加一次结束指针,您就增加一次中间a,直到结束指针到达末尾。假设您有一个
std::list l
std::list<T>::iterator i = l.begin();
std::list<T>::iterator m = l.begin();
bool even = true;
while (i != list.end())
{
if (even) ++m;
++i;
even = !even;
}
std::list::iterator i=l.begin();
std::list::迭代器m=l.begin();
布尔偶数=真;
while(i!=list.end())
{
if(偶数)++m;
++一,;
偶数=!偶数;
}
现在
m
指向l
的中间,以下是步骤:
std::list<T>::iterator i = l.begin();
std::list<T>::iterator m = l.begin();
bool even = true;
while (i != list.end())
{
if (even) ++m;
++i;
even = !even;
}
- 取两个指针
和*p1
,指向链接的头 名单*p2
- 启动一个循环并递增
,2次(使用空检查)*p2
- 如果
不为空,则将*p2
增加1次*p1
- 当
达到空值时,您的*p2
位于中心*p1
[注意:如果处理容器类型的链表,可以使用迭代器而不是指针]使用两个指针。将第一个指针移动两个节点,将第二个指针移动一个节点。当第一个指针到达末尾时,第二个指针将指向中间
// How to find the middle node of a single linked list in a single traversal
// 1. The length of the list is not given
// 2. If the number of nodes is even, there are two middle nodes,
// return the first one.
Node* MiddleNode(Node* const head)
{
if (!head)
{
return head;
}
Node* p1 = head, * p2 = head->next;
while (p2 && p2->next)
{
p1 = p1->next;
p2 = p2->next->next;
}
return p1;
}
试试这段代码这是我的第一个想法,但它仍然是“只有一次遍历”吗“?是的,因为您只有一个循环。如果这是作业,我不知道这是否是作业的目的,但出于实际的目的,这一次遍历了列表。真正的答案应该是这样的,因为如果你从循环构造中考虑任务,当前的答案只能保持单次遍历规则。但实际扫描次数至少为1.5N。我看不出我的答案和接受的答案之间有任何区别,它们做的是相同的事情。在首次
advance b
之后,您必须检查空值。否则就崩溃!取决于准确的问题陈述。如果给定列表的中间位置,则其长度必须为奇数。你可以在循环之前<代码>提前B/COD>。“你是正确的,不能崩溃:”但是,我用C++替换了代码,它说明并解决了你所描述的问题。如果它有偶数个节点,我们怎么能照顾一个链表?如果我们在继续之前不检查空,它会给崩溃RI8。虽然这确实是希望的答案,但我从来没有理解为什么它会考虑一个单一的遍历。实际上是两次(或1.5次)并行遍历,指针/迭代器增量不少于两次(1.5次)串行遍历。这是避免计数器,但不是任何遍历。