web-dev-qa-db-fra.com

Comment trouver un élément intermédiaire dans une liste de liens sans parcourir la liste entière?

Comment trouver un élément intermédiaire dans une liste de liens sans avoir à parcourir toute la liste. ? ... et au maximum, vous ne pouvez utiliser que 2 pointeurs ... comment faire? .... et aussi la longueur de la liste n'est pas donnée.

13
RAM

Je ne vois pas comment vous pourriez le faire sans parcourir toute la liste à moins de connaître la longueur.

Je suppose que la réponse veut qu'un pointeur traverse un élément à la fois, tandis que le second déplace deux éléments à la fois.
Ainsi, lorsque le second pointeur aura atteint la fin, le premier pointeur sera au milieu.

26

Le code ci-dessous vous aidera à obtenir l'élément central . Vous devez utiliser deux pointeurs "rapide" et "lent". A chaque étape, le pointeur rapide augmentera de deux et plus lentement, de un. Lorsque la liste se termine, le pointeur lent se trouve au milieu. 

Considérons que la Node ressemble à ceci

class Node
{
  int data;
  Node next;
}

Et LinkedList a une méthode getter pour fournir la tête de la liste liée 

public Node getHead()
{
  return this.head;
}

La méthode ci-dessous va obtenir l'élément central de la liste (sans connaître la taille de la liste)

public int getMiddleElement(LinkedList l)
{
    return getMiddleElement(l.getHead());
}

private int getMiddleElement(Node n)
{
    Node slow = n;
    Node fast = n;

    while(fast!=null && fast.next!=null)
    {
        fast = fast.next.next;
        slow = slow.next;
    }

    return slow.data;
}

Exemple:
Si la liste est 1-2-3-4-5, l'élément du milieu est 3
Si la liste est 1-2-3-4, l'élément du milieu est 3

11
asifsid88

En C, en utilisant des pointeurs, pour être complet. Notez que ceci est basé sur l'algorithme " Tortoise and Hare " utilisé pour vérifier si une liste liée contient un cycle.

Notre noeud est défini comme suit:

typedef struct node {
    int          val;
    struct node *next;
} node_t;

Alors notre algorithme est donc:

node_t *
list_middle (node_t *root)
{
    node_t *tort = root;
    node_t *hare = root;

    while (hare != NULL && hare->next != NULL) {
        tort = tort->next;
        hare = hare->next->next;
    }

    return (tort);
}

Pour une liste avec un nombre pair de noeuds, cela retourne le noeud qui traite le centre actuel (par exemple, dans une liste de 10 noeuds, cela retournera le noeud 6).

1
Richard Horrocks

Pour une liste doublement liée avec des pointeurs donnés aux nœuds de tête et de queue 
nous pouvons utiliser à la fois la traversée de la tête et de la queue 

p = head;
q = tail;
while(p != q && p->next != q)
{
    p = p->next;
    q = q->prev;
}
return p;

Introduire un pointeur sur le nœud du milieu peut être une option mais des fonctions comme 
insertNode et deleteNode doivent modifier ce pointeur

0
J Doe

Code Python pour l'élément central utilisant la méthode des deux pointeurs:

class Node:
    def __init__(self,data):
        self.data=data
        self.next=None

class LinkedList:
    def __init__(self):
        self.head=None

    def printList(self):
        temp=self.head
        while(temp):
            print(temp.data,end=" ")
            temp=temp.next

    def insertAtBeg(self,new_data):
        new_node=Node(new_data)
        if self.head is None:
            self.head=new_node
            return

        new_node.next=self.head
        self.head=new_node

    def findMiddle(self):
        fast_ptr=self.head
        slow_ptr=self.head

        if(self.head is not None):
            while(fast_ptr is not None and fast_ptr.next is not None):
                fast_ptr=fast_ptr.next.next
                slow_ptr=slow_ptr.next
            print('Middle Element is '+ str (slow_ptr.data))

if __name__=='__main__':
    mylist=LinkedList()
    mylist.insertAtBeg(10)
    mylist.insertAtBeg(20)
    mylist.insertAtBeg(30)
    mylist.findMiddle()

Sortie: L'élément central est 20

0
gajendra30

Les méthodes Java ci-dessous trouvent le milieu d'une liste liée. Il utilise deux pointeurs 1) Les pointeurs lents qui se déplacent d’un point à chaque itération 2) Le pointeur rapide qui se déplace deux fois à chaque itération Le pointeur lent pointe au milieu lorsque la vitesse atteint la fin de la liste. 

public SinglyLinkedListNode getMiddle(SinglyLinkedListNode list) {
        if (list == null)
            return null;
        SinglyLinkedListNode fastPtr = list.next;
        SinglyLinkedListNode slowPtr = list;
        while (fastPtr != null) {
            fastPtr = fastPtr.next;
            if (fastPtr != null) {
                slowPtr = slowPtr.next;
                fastPtr = fastPtr.next;
            }
        }

        return slowPtr;
    }
0
Debapriya Biswas
LinkedList.Node current = head;
  int length = 0;
  LinkedList.Node middle = head;

  while(current.next() != null){
      length++;
      if(length%2 ==0){
          middle = middle.next();
      }
      current = current.next();
  }

  if(length%2 == 1){
      middle = middle.next();
  }

  System.out.println("length of LinkedList: " + length);
  System.out.println("middle element of LinkedList : " + middle);
0
Laila Al-Saadi

Utilisation de C # pour trouver un élément central de la liste liée 

    static void Main(string[] args)
    {
        LinkedList<int> linked = new LinkedList<int>();
        linked.AddLast(1);
        linked.AddLast(3);
        linked.AddLast(5);
        linked.AddLast(6);
        linked.AddFirst(12);

        Console.WriteLine("Middle Element - "+ListMiddle<int>(linked));
        Console.ReadLine(); }   

public static T ListMiddle<T>(IEnumerable<T> input)
    {
        if (input == null)
            return default(T);

        var slow = input.GetEnumerator();
        var fast = input.GetEnumerator();

        while (slow.MoveNext())
        {
            if (fast.MoveNext())
            {
                if (!fast.MoveNext())
                    return slow.Current;
            }
            else
            {
                return slow.Current;
            }
        }
        return slow.Current;
    }
0
ravithejag

Il y a deux réponses possibles, une pour impaire et une pour paire, les deux ayant le même algorithme

Pour les chiffres impairs: un pointeur se déplace d’un pas et le deuxième pointeur déplace deux éléments comme une heure et lorsque les deuxièmes éléments atteignent le dernier élément, l’élément auquel le premier pointeur se trouve est l’élément médian. Très facile pour un couple .. ... Essayez: 1 2 3 4 5

Pour pair: identique, un pointeur se déplace d'un pas et le deuxième pointeur déplace deux éléments comme une heure et lorsque les deuxièmes éléments ne peuvent pas passer à l'élément suivant, l'élément auquel le premier pointeur se trouve, l'élément mid . Try: 1 2 3 4 

0
Rushabh Shah

En utilisant une variable de taille, vous pouvez conserver la taille de la liste liée.

public class LinkedList {
private Node headnode;
private int size;


public void add(int i){
    Node node = new Node(i);
    node.nextNode = headnode;

    headnode = node;
    size++;
}

public void findMiddleNode(LinkedList linkedList, int middle) {
    Node headnode = linkedList.getHeadnode();
    int count = -1;
    while (headnode!=null){
        count++;

        if(count == middle){
            System.out.println(headnode.data);
        }else {
            headnode = headnode.nextNode;
        }

    }
}


private class Node {
    private Node nextNode;
    private int data;

    public Node(int data) {
        this.data = data;
        this.nextNode = null;
    }
}

public Node getHeadnode() {
    return headnode;
}

public int getSize() {
    return size;
}
}

Ensuite, à partir d’une méthode client, trouvez le milieu de la taille de la liste:

public class MainLinkedList {
public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add(5);
    linkedList.add(3);
    linkedList.add(9);
    linkedList.add(4);
    linkedList.add(7);
    linkedList.add(99);
    linkedList.add(34);
    linkedList.add(798);
    linkedList.add(45);
    linkedList.add(99);
    linkedList.add(46);
    linkedList.add(22);
    linkedList.add(22);


    System.out.println(linkedList.getSize());

    int middle = linkedList.getSize()/2;

    linkedList.findMiddleNode(linkedList, middle);

}
}

Je ne sais pas si cela vaut mieux que la méthode à deux nœuds, mais ici aussi, vous ne devez pas traverser toute la boucle.

0
Nagendra Singh