如何在单个遍历中找到单个链表的中间节点(如果未给出列表的长度)

时间:2011-07-15 07:32:18

标签: c++ linked-list

我有一个问题陈述,如:“如何在一次遍历中找到单链表的中间节点,而扭曲是我们不知道链表中的节点数?”

我有一个答案,比如“当你遍历链表并递增一个计数器直到你到达列表的末尾时,取一个向量并开始推送所有节点的地址”。所以最后我们可以得到列表中的节点数,如果是偶数(计数器/ 2)或奇数(计数器/ 2 +计数器%2)给出中间节点数,我们可以得到vectore.at(middlenodenumber)指向中间节点“。

这很好......但这是浪费内存存储一个非常大的链表的所有地址!那么我们如何才能有更好的解决方案?

7 个答案:

答案 0 :(得分:22)

以下是步骤:

  • 两个指针*p1*p2指向链接的头部 列表
  • 启动循环并增加*p2,2次(使用空检查)
  • 如果*p2不为null,则增加*p1 1次
  • *p2达到null时;你有*p1在中心

[注意:如果处理容器类型链表,可以使用迭代器而不是指针]

答案 1 :(得分:10)

假设您有std::list<T> 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;
}

现在m指向l的中间位置。

答案 2 :(得分:1)

您可以使用带有两个迭代器的单个循环,比如it1it2,其中只在循环的每第二次迭代中递增it2it1到达列表末尾时终止。 it2现在将指向列表的中间元素。

答案 3 :(得分:0)

试试这个:
你有2个指针。一个指向中间,另一个指向结尾,两个指向开始时列表的开头。每次第二次成功递增结束指针时,都会在一次中间递增,直到结束指针到达结尾。

答案 4 :(得分:0)

使用两个指针。将第一个指针移动两个节点,将第二个指针移动一个节点。当第一个指针到达结尾时,第二个指针将指向中间。

答案 5 :(得分:0)

// 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;
}

答案 6 :(得分:0)

SLNode* mid(SLNode *head) 

{

SLNode *one = head;

SLNode *two = head;


    while(one != nullptr) {
        one = one->next;
        two = two->next;
        if(one != nullptr) {
            one = one->next;
            //two = two->next;
        }
    }
    return two;
}

试试这段代码