【问题标题】:How to find the middle node of a single linked list in a single traversal (if the length of the list is not given)如何在单次遍历中找到单个链表的中间节点(如果没有给出链表的长度)
【发布时间】:2011-07-15 07:32:18
【问题描述】:

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

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

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

【问题讨论】:

    标签: c++ linked-list


    【解决方案1】:

    以下是步骤:

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

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

    【讨论】:

    • 虽然这肯定是想要的答案,但我不明白为什么它被认为是单次遍历。它实际上是两个(或 1.5)并行遍历,并且指针/迭代器增量不少于两个(1.5)串行遍历。它避免了一个计数器,但没有任何遍历。
    【解决方案2】:

    假设你有一个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 的中间。

    【讨论】:

    • 在第一个 advance b 之后,您必须检查空值。否则崩溃!
    • 取决于确切的问题陈述。如果给定列表的中间位置,那么它的长度一定是奇数。然后你可以在循环之前advance b
    • @iammilind 伪代码不会崩溃 :) 但你说得对,我用 C++ 替换了代码,这说明并解决了你描述的问题。
    • 如果链表中有偶数个节点,我们如何处理它。如果我们在继续之前不检查 null,它会导致 ri8 崩溃!
    【解决方案3】:

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

    【讨论】:

    • 这是我的第一个想法,但它仍然是“只有一次遍历”吗?
    • 是的,因为你只有一个循环。如果这是家庭作业,我不知道这是否是作业的目的,但出于所有实际目的,它会遍历列表一次。
    • 真正的答案应该是这样,因为当前的答案只有在您考虑循环构造中的任务时才正式保持单次遍历规则。但实际扫描次数至少为1.5N。
    • 我看不出我的答案和接受的答案有什么区别,他们做同样的事情。
    【解决方案4】:

    试试这个:
    你有2个指针。一个指向中间,另一个指向结尾,都指向列表的开头。每成功增加一次结束指针,你就增加一次 mid 一次,直到结束指针到达末尾。

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:
        // 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;
        }
        

        【讨论】:

          【解决方案7】:
          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;
          }
          

          试试这个代码

          【讨论】:

            猜你喜欢
            • 2011-06-10
            • 2012-08-08
            • 2018-11-12
            • 1970-01-01
            • 2019-11-08
            • 2011-11-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多