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.
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.
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
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).
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
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
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;
}
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);
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;
}
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
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.