如何找到链接列表中的项目总数?

时间:2019-02-26 06:23:39

标签: algorithm data-structures linked-list floyd-cycle-finding

我有一个循环的链接列表,我想找出此列表中元素的总数。如何实现呢?

5 个答案:

答案 0 :(得分:2)

我能想到的一种解决方案是维护两个指针。第一个指针(* start)将始终指向起始节点,例如节点A。 另一个指针(* current)将初始化为:current = start-> next。

现在,只需使用current-> next迭代每个节点,直到它指向开始。 并继续增加一个计数器:numberOfNodes ++;

代码如下:

public int countNumberOfItems(Node* start){
Node* current = start -> next;

int numberOfNodes = 1; //Atleast the starting node is there.

while(current->next != start){
   numberOfNodes++;
   current = current->next;
}
return numberOfNodes; 
}

答案 1 :(得分:0)

您只想对链接列表中的节点计数吧?我在下面放一个例子。但是,在您的情况下,存在一个周期,因此,您还需要检测到该周期,以免多次计数某些节点。 我已经更正了我的答案,现在有一个普通的计数和循环计数(使用快速指针和慢速指针)。

static int count( Node n)  
{  
    int res = 1;  
    Node temp = n;  
    while (temp.next != n)  
    {  
        res++;  
        temp = temp.next;  
    }  
    return res;  
}  

static int countInLoop( Node list)  
{  
    Node s_pointer = list, f_pointer = list;  

    while (s_pointer !=null && f_pointer!=null && f_pointer.next!=null)  
    {  
        s_pointer = s_pointer.next;  
        f_pointer = f_pointer.next.next;  

        if (s_pointer == f_pointer)  
            return count(s_pointer);  
    }  

    return 0;  
} 

答案 2 :(得分:0)

比方说,列表在循环之前有x个节点,在循环中有y个节点。运行Floyd循环检测,计算慢步数s。一旦检测到汇合点,请再次遍历循环以获取y

现在,从列表头开始,执行s - y步,到达节点N。最后,从NM运行两个慢速指针,直到它们相遇为止,进行t步骤。说服自己(或更好地证明)他们在列表的初始部分进入循环的地方相遇。

因此,初始部分具有s - y + t + 1个节点,并且循环由y个节点形成,总共有s + t + 1个。

答案 3 :(得分:0)

首先使用弗洛伊德循环检测算法找到循环,并在检查循环后发现循环,并保持计数,然后打印相同的计数。

    function LinkedList() {
      let length = 0; 
      let head = null; 

      let Node = function(element) {
        this.element = element; 
        this.next = null;
      }

      this.head = function() {
        return head;
      };

    this.add = function(element) {
      let node = new Node(element);
      if(head === null){
          head = node;
      } else {
          let currentNode = head;
          while(currentNode.next) {
              currentNode = currentNode.next;
          }
          currentNode.next = node;
      }
    };
      this.detectLoopWithCount = function() {
        head.next.next.next.next.next.next.next.next = head; // make cycle
        let fastPtr = head;
        let slowPtr = head;
        let count = 0;
        while(slowPtr && fastPtr && fastPtr.next) {
          count++;
          slowPtr = slowPtr.next;
          fastPtr = fastPtr.next.next;
          if (slowPtr == fastPtr) {
            console.log("\n Bingo :-) Cycle found ..!! \n ");
            console.log('Total no. of elements = ', count);
            return;
          }
        }
      }
    
    }
    let mylist = new LinkedList();
      mylist.add('list1');
      mylist.add('list2');
      mylist.add('list3');
      mylist.add('list4');
      mylist.add('list5');
      mylist.add('list6');
      mylist.add('list7');
      mylist.add('list8');
      mylist.detectLoopWithCount();

答案 4 :(得分:0)

有一个“慢”指针,它一次移动一个节点。有一个“快速”指针,其移动速度快两倍,一次移动两个节点。

可视化的慢速指针和快速指针在具有10个节点的链表中移动:

1: |sf--------|
2: |-s-f------|
3: |--s--f----|
4: |---s---f--|
5: |----s----f|

在这一点上,有两件事是正确的:1)链表没有循环(用fast!= null && fast.next!= null检查)或2)确实循环了。让我们继续可视化,假设它确实循环了:

6: |-f----s---|
7: |---f---s--|
8: |-----f--s-|
9: |-------f-s|
10: s == f

如果链表未循环,则快速指针在O(n / 2)时间结束比赛;我们可以删除该常数并将其称为O(n)。如果链表确实循环,则慢速指针将在整个链表中移动,并最终在O(n)时间等于快速指针。