如何找到链表中循环的节点数量?

3
如何找到链表循环中的节点数?
例如:
A ----> B ----> C -----> D -----> E
                Λ                 |
                |                 |
                |                 V
                H <----- G <----- F 

查找从C到H的循环中的节点数

基本问题是如何找到点C。我们可以使用传统的乌龟和兔子算法,但它并不总是在点C相遇。


如果你只需要循环的大小而不是从A到C的距离,那么它们在C中相遇并不重要。 - ruslik
5个回答

4

在这里查看更多关于如何在链表中找到循环的解决方案。添加节点计数非常简单。(尽管乌龟和兔子可能是最好的方法)


2

如果您只是想找到答案,请使用“龟兔赛跑”算法确定是否存在循环。然后启动一个计数器,并计算需要多少次迭代才能到达您最初发现的点。这可能不是最有效的方法,但它可以给出正确的答案。

以下是一些C++代码:

#include <iostream>

struct node
{
  node(node* next)
    : next(next)
  { }

  node* next;
};

int main(int argc, char* argv[])
{
  node h(NULL), g(&h), f(&g), e(&f), d(&e), c(&d), b(&c), a(&b);
  h.next = &c;

  node* tortoise = &a;
  node* hare = &b;

  while(tortoise != hare)
  {
    tortoise = tortoise->next;
    hare = hare->next->next;
  }

  int count = 1;
  tortoise = tortoise->next;

  while(tortoise != hare)
  {
    ++count;
    tortoise = tortoise->next;
  }

  std::cout << "Size of cycle: " << count << "\n";

  return 0;
}

请注意,如果您没有实际上的循环,而是在循环中到达了末尾,那么您需要做一些额外的工作来确定是否到达了末尾。传统的乌龟和兔子算法可以解决这个问题: http://en.wikipedia.org/wiki/Cycle_detection

1
List visited;
List toVisit;

toVisit.add(A);                         // add the first Node
while(toVisit is not empty){
  Node current = visited.remove();
  Array <Node> links = current.getLinks();
  for(int i=0; i<links.size(); i++){
    if(!visited.contains(links[i])){    // if the link has NOT already been visited add it to the toVisit List
      toVisit.add(links[i]);
    }        
  visited.add(current);                 // mark current as visited
  }
}
return visited.size();                  // to get the number of nodes in the graph

0

我认为这不应该被视为一个链表。通常,链表以空指针或指向结束符号的指针结尾。即:start -> A -> B -> C -> end。我认为这将是一种特定类型的图形。

要找到图中节点的总数,我会这样做:

List visited;
List toVisit;

toVisit.add(A);                         // add the first Node
while(toVisit is not empty){
  Node current = visited.remove();
  Array <Node> links = current.getLinks();
  for(int i=0; i<links.size(); i++){
    if(!visited.contains(links[i])){    // if the link has NOT already been visited add it to the toVisit List
      toVisit.add(links[i]);
    }        
  visited.add(current);                 // mark current as visited
  }
}
return visited.size();                  // to get the number of nodes in the graph

如果你总是知道会有一个循环(请注意...):
A ---> ... ---> C -----> D -----> E
                Λ                 |
                |                 |
                |                 V
                ... <----- G <--- F 

你可以像这样修改代码:
List visited;

Node current = firstNode;
while(!visited.contains(firstNode)){
  Node next = current.getNext();      
  visited.add(current);                       // mark current as visited
  current=next;
}
// our ending condition is when we have found the same node again.  
int currentIndex = visited.indexOf(current);
int size = visited.size();
int sizeOfLoop = size - currentIndex;
return sizeOfLoop;

0

1) Floyd算法找到循环 2) 当slow_ptr = fast_ptr时,找到循环中的节点数(k)

此外还可以这样转换成C语言: 3) 从头开始用两个指针,一个指向头部,另一个指向head + k。 4) 你会在循环的起点相遇(C)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接