链表中间

时间:2009-11-17 04:30:52

标签: c++

当我们没有被告知它的大小时如何找到链表的中间部分,并且必须仅使用一个循环和仅一个指针来执行。

7 个答案:

答案 0 :(得分:13)

怎么样

LinkedList * llist = getLList(); // the linked list
Node * node = llist.head;

while ( node ) {
    node = node.next;
    if ( node ) {
        node  = node.next;
        llist.remove( llist.head );
    }
}
// now llist.head is (er, um... was) the middle node.  
// hope you didn't need the rest of the list.

答案 1 :(得分:8)

Node *m,*e,*head; /* head is given */
m=e=head;
while(e) {
  e=e->next;
  if (e) {
    e=e->next;
    m=m->next;
  }
}
/* now m is the middle node */

抱歉,我必须使用2个指针:)


将此添加到您的答案中,因为小调整会将指针数量减少到1.我希望您不介意:

Node m,*e,*head; /* head is given */
e = head;
if (e) m = *e;
while(e) {
  e = e->next;
  if (e) {
    e = e->next;
    m = *(m.next);
  }
}
/* now m is the middle node */

答案 2 :(得分:2)

嗯,这有点像黑客,因为它在功能上等同于2个循环。但是,它只是一个循环。

Node* middle(Node* const begin)
{
    Node* current = begin;
    bool size_known = false;
    int size = 0;
    while (true)
    {
        if (!size_known)
        {
            if (current)
            {
                ++size;
                current = current->next;
            }
            else
            {
                current = begin;
                size_known = true;
            }
        }
        else
        {
            if (size <= 1)
                return current;
            current = current->next;
            size -= 2;
        }
    }
}

答案 3 :(得分:1)

查看我的代码。它正确地在我的FC9 x86_64上工作,函数“middle()”就是你想要的:

static struct node *middle(struct node *head)
{
        struct node *mid = head;
        int flag = 0;
        while (NULL != head) {
                head = head->next;
                flag = !flag;
                if (flag) {
                        mid = mid->next;
                }
        }
        return mid;
}

编辑:删除除中间()之外的代码。

答案 4 :(得分:1)

在这种情况下我们可以使用跳过列表:

1)遍历链接列表中的每个节点时,会生成奇数节点的跳过列表。时间:O(n)空间:O(n / 2)

2)现在当你到达列表的末尾时,将legnth除以2并加1以获得中间元素索引。

3)在跳过列表O(登录)时间内搜索索引。

因此,算法的整体时间复杂度将是:

O(n)(1遍历)+ O(logn)(搜索跳过列表)= O(n) 空间复杂度:O(n / 2)

请回复这是否效率低......

答案 5 :(得分:0)

使用提供的头指针迭代你的列表,并递增你的一个允许指针(我假设你的一个含糊不清的问题,你允许一个指针除了传入的那个)一次对于头指针的每两个增量。

Node* middle( Node* head )
{
    Node* middle = head;
    while (head != NULL) {
        head = head->next;

        if (head->next != NULL) {
            head = head->next;
            middle = middle->next;
        }
    }
    return middle;
}

这里忽略了边缘情况(就像具有偶数元素的列表的中间部分一样)。

答案 6 :(得分:-1)

自已标记c ++以来,C ++查找列表中间位置的方法:

#include <list> 
using namespace std;

using IntegerList = list<int>; 

int main() { 
     IntegerList l; 
     for (int i : {0, 1, 2, 3, 4, 5, 6})
          l.push_back(i * 1); 

     auto m = l.begin(); 
     bool even = false; 
     for(auto &z:l) { 
         if (even) ++m; 
         even = !even; 
     }

     cout << "\nmiddle of the list:" << *m << "\n";
}