Che cos'è l'elenco collegato circolare?
IL elenco collegato circolare è un elenco collegato in cui tutti i nodi sono collegati per formare un cerchio. In una lista concatenata circolare, il primo nodo e l'ultimo nodo sono collegati tra loro formando un cerchio. Non c'è NULL alla fine.
Elenco collegato circolare
Esistono generalmente due tipi di elenchi collegati circolari:
- Elenco circolare collegato singolarmente: In una lista circolare collegata singolarmente, l'ultimo nodo della lista contiene un puntatore al primo nodo della lista. Attraversiamo l'elenco circolare collegato singolarmente fino a raggiungere lo stesso nodo da cui siamo partiti. L'elenco circolare collegato singolarmente non ha inizio né fine. Nessun valore nullo è presente nella parte successiva di nessuno dei nodi.

Rappresentazione di liste circolari singolarmente collegate
numeri per l'alfabeto
- Circolare Elenco doppiamente collegato: La lista circolare doppiamente concatenata ha proprietà sia della lista doppiamente concatenata che della lista concatenata circolare in cui due elementi consecutivi sono collegati o collegati dal puntatore precedente e successivo e l'ultimo nodo punta al primo nodo dal puntatore successivo e anche il primo nodo punta a l'ultimo nodo dal puntatore precedente.

Rappresentazione di lista circolare doppiamente concatenata
Nota: Utilizzeremo la singola lista concatenata circolare per rappresentare il funzionamento della lista concatenata circolare.
Rappresentazione della lista circolare circolare:
Gli elenchi collegati circolari sono simili ai singoli elenchi collegati con l'eccezione del collegamento dell'ultimo nodo al primo nodo.
Rappresentazione del nodo di una lista concatenata circolare:
C++
// Class Node, similar to the linked list class Node{ int value; // Points to the next node. Node next; }>
C struct Node { int data; struct Node *next; };>
Giava public class Node { int data; Node next; public Node(int data) { this.data = data; this.next = null; } }>
C# public class Node { public int data; public Node next; public Node(int data) { this.data = data; this.next = null; } }>
Javascript class Node { constructor(data) { this.data = data; this.next = null; } }>
PHP class Node { public $data; public $next; function __construct($data) { $this->dati = $dati; $questo->successivo = null; } }>
Python3 # Class Node, similar to the linked list class Node: def __init__(self,data): self.data = data self.next = None>
Esempio di lista circolare collegata singolarmente:

Esempio di lista concatenata circolare
La suddetta lista circolare singolarmente collegata può essere rappresentata come:
C++ // Initialize the Nodes. Node one = new Node(3); Node two = new Node(5); Node three = new Node(9); // Connect nodes one.next = two; two.next = three; three.next = one;>
C Node* one = createNode(3); Node* two = createNode(5); Node* three = createNode(9); // Connect nodes one->successivo = due; due->successivo = tre; tre->successivo = uno;>
Giava // Define the Node class class Node { int value; Node next; public Node(int value) { this.value = value; } } // Initialize the Nodes. Node one = new Node(3); Node two = new Node(5); Node three = new Node(9); // Connect nodes one.next = two; two.next = three; three.next = one;>
C# Node one = new Node(3); Node two = new Node(5); Node three = new Node(9); // Connect nodes one.next = two; two.next = three; three.next = one;>
Javascript let one = new Node(3); let two = new Node(5); let three = new Node(9); // Connect nodes one.next = two; two.next = three; three.next = one;>
PHP $one = new Node(3); $two = new Node(5); $three = new Node(9); // Connect nodes $one->successivo = $due; $due->successivo = $tre; $tre->successivo = $uno;>
Python3 # Initialize the Nodes. one = Node(3) two = Node(5) three = Node(9) # Connect nodes one.next = two two.next = three three.next = one>
Spiegazione: Nel programma precedente uno, due e tre sono i nodi rispettivamente con i valori 3, 5 e 9 che sono collegati in modo circolare come:
- Per il nodo uno: Il puntatore Next memorizza l'indirizzo del nodo due.
- Per il nodo due: Il Next memorizza l'indirizzo del Nodo tre
- Per il nodo tre: IL Next punta al nodo uno.
Operazioni sulla lista concatenata circolare:
Possiamo eseguire alcune operazioni sulla lista concatenata circolare simili alla lista concatenata singola che sono:
- Inserimento
- Cancellazione
1. Inserimento nella lista collegata circolare:
Un nodo può essere aggiunto in tre modi:
- Inserimento all'inizio della lista
- Inserimento a fine lista
- Inserimento tra i nodi
1) Inserimento all'inizio della lista: Per inserire un nodo all'inizio dell'elenco, attenersi alla seguente procedura:
- Crea un nodo, diciamo T.
- Rendi T -> successivo = ultimo -> successivo.
- ultimo -> successivo = T.

Elenco collegato circolare prima dell'inserimento
Poi,

Elenco collegato circolare dopo l'inserimento
2) Inserimento a fine lista: Per inserire un nodo alla fine dell'elenco, attenersi alla seguente procedura:
- Crea un nodo, diciamo T.
- Rendi T -> successivo = ultimo -> successivo;
- ultimo -> successivo = T.
- ultimo = T.
Prima dell'inserimento,

Elenco concatenato circolare prima dell'inserimento del nodo alla fine
hashset vs hashmap
Dopo l'inserimento,

Elenco concatenato circolare dopo l'inserimento del nodo alla fine
3) Inserimento tra i nodi: Per inserire un nodo tra i due nodi, attenersi alla seguente procedura:
- Crea un nodo, diciamo T.
- Cerca il nodo dopo il quale deve essere inserito T, diciamo che il nodo è P.
- Rendi T -> successivo = P -> successivo;
- P -> successivo = T.
Supponiamo che sia necessario inserire 12 dopo che il nodo ha il valore 10,

Elenco collegato circolare prima dell'inserimento
Dopo la ricerca e l'inserimento,

Elenco collegato circolare dopo l'inserimento
2. Cancellazione in una lista circolare collegata:
1) Elimina il nodo solo se è l'unico nodo nella lista collegata circolare:
dove è inserire il tasto sulla tastiera del laptop
- Libera la memoria del nodo
- L'ultimo valore dovrebbe essere NULL Un nodo punta sempre a un altro nodo, quindi l'assegnazione NULL non è necessaria.
Qualsiasi nodo può essere impostato come punto di partenza.
I nodi vengono attraversati rapidamente dal primo all'ultimo.
2) Cancellazione dell'ultimo nodo:
- Individua il nodo prima dell'ultimo nodo (lascia che sia temporaneo)
- Mantieni l'indirizzo del nodo accanto all'ultimo nodo in temp
- Cancella l'ultimo ricordo
- Metti la temperatura alla fine
3) Elimina qualsiasi nodo dall'elenco collegato circolare: Ci verrà assegnato un nodo e il nostro compito è eliminare quel nodo dall'elenco collegato circolare.
Algoritmo:
Caso 1 : L'elenco è vuoto.
- Se l'elenco è vuoto, ritorneremo semplicemente.
Caso 2 :L'elenco non è vuoto
- Se la lista non è vuota allora definiamo due puntatori corr E prec e inizializzare il puntatore corr con il Testa nodo.
- Attraversa l'elenco utilizzando corr per trovare il nodo da eliminare e prima di passare a curr al nodo successivo, impostare ogni volta prev = curr.
- Se il nodo viene trovato, controlla se è l'unico nodo nell'elenco. Se sì, imposta head = NULL e free(curr).
- Se l'elenco ha più di un nodo, controlla se è il primo nodo dell'elenco. Condizione per verificare questo (curr == head). Se sì, spostati indietro fino a raggiungere l'ultimo nodo. Dopo che prev raggiunge l'ultimo nodo, imposta head = head -> next e prev -> next = head. Elimina corr.
- Se curr non è il primo nodo, controlliamo se è l'ultimo nodo nell'elenco. La condizione per verificarlo è (curr -> next == head).
- Se curr è l'ultimo nodo. Imposta prev -> next = head ed elimina il nodo curr con free(curr).
- Se il nodo da eliminare non è né il primo né l'ultimo nodo, impostare prev -> next = curr -> next ed eliminare curr.
- Se il nodo non è presente nella lista ritorna head e non fa nulla.
Di seguito è riportata l'implementazione dell'approccio di cui sopra:
C++ // C++ program to delete a given key from // linked list. #include using namespace std; // Structure for a node class Node { public: int data; Node* next; }; // Function to insert a node at the // beginning of a Circular linked list void push(Node** head_ref, int data) { // Create a new node and make head // as next of it. Node* ptr1 = new Node(); ptr1->dati = dati; ptr1->successivo = *head_ref; // Se l'elenco collegato non è NULL allora // imposta il successivo dell'ultimo nodo if (*head_ref != NULL) { // Trova il nodo prima di head e // aggiorna quello successivo. Nodo* temp = *head_ref; while (temp->next != *head_ref) temp = temp->next; temp->successivo = ptr1; } else // Per il primo nodo ptr1->next = ptr1; *rif_testa = ptr1; } // Funzione per stampare i nodi in una data // lista concatenata circolare void printList(Node* head) { Node* temp = head; if (testa!= NULL) { do { cout<< temp->dati<< ' '; temp = temp->Prossimo; } while (temp!= testa); } cout<< endl; } // Function to delete a given node // from the list void deleteNode(Node** head, int key) { // If linked list is empty if (*head == NULL) return; // If the list contains only a // single node if ((*head)->dati == chiave && (*head)->successivo == *head) { free(*head); *testa = NULL; ritorno; } Nodo *ultimo = *testa, *d; // Se head deve essere cancellato if ((*head)->data == key) { // Trova l'ultimo nodo della lista while (last->next != *head) last = last->next; // Punta l'ultimo nodo al successivo // head cioè il secondo nodo // della lista last->next = (*head)->next; libero(*testa); *testa = ultimo->successivo; ritorno; } // Il nodo da eliminare non è // trovato oppure la fine della lista // non è stata raggiunta while (last->next != *head && last->next->data != key) { last = last ->successivo; } // Se è stato trovato il nodo da eliminare if (last->next->data == key) { d = last->next; ultimo->successivo = d->successivo; liberato); } altrimenti cout<< 'Given node is not found in the list!!!
'; } // Driver code int main() { // Initialize lists as empty Node* head = NULL; // Created linked list will be // 2->5->7->8->10 spinta(&testa, 2); spingere(&testa, 5); spingi(&testa, 7); spingere(&testa, 8); spingi(&testa, 10); cout<< 'List Before Deletion: '; printList(head); deleteNode(&head, 7); cout << 'List After Deletion: '; printList(head); return 0; }>
C #include #include // Structure for a node struct Node { int data; struct Node* next; }; // Function to insert a node at the // beginning of a Circular linked list void push(struct Node** head_ref, int data) { // Create a new node and make head // as next of it. struct Node* ptr1 = (struct Node*)malloc(sizeof(struct Node)); ptr1->dati = dati; ptr1->successivo = *head_ref; // Se l'elenco collegato non è NULL allora // imposta il successivo dell'ultimo nodo if (*head_ref != NULL) { // Trova il nodo prima di head e // aggiorna quello successivo. struct Node* temp = *head_ref; while (temp->next != *head_ref) temp = temp->next; temp->successivo = ptr1; } else // Per il primo nodo ptr1->next = ptr1; *rif_testa = ptr1; } // Funzione per stampare i nodi in una data // lista concatenata circolare void printList(struct Node* head) { struct Node* temp = head; if (head != NULL) { do { printf('%d ', temp->data); temp = temp->successivo; } while (temp!= testa); } printf('
'); } // Funzione per eliminare un dato nodo // dalla lista void deleteNode(struct Node** head, int key) { // Se la lista collegata è vuota if (*head == NULL) return; // Se l'elenco contiene solo un // singolo nodo if ((*head)->data == key && (*head)->next == *head) { free(*head); *testa = NULL; ritorno; } struct Nodo *last = *head, *d; // Se head deve essere cancellato if ((*head)->data == key) { // Trova l'ultimo nodo della lista while (last->next != *head) last = last->next; // Punta l'ultimo nodo al successivo // head cioè il secondo nodo // della lista last->next = (*head)->next; libero(*testa); *testa = ultimo->successivo; ritorno; } // Il nodo da eliminare non è // trovato oppure la fine della lista // non è stata raggiunta while (last->next != *head && last->next->data != key) { last = last ->successivo; } // Se è stato trovato il nodo da eliminare if (last->next->data == key) { d = last->next; ultimo->successivo = d->successivo; liberato); } else printf('Il nodo indicato non è stato trovato nell'elenco!!!
'); } // Codice driver int main() { // Inizializza gli elenchi come struttura vuota Node* head = NULL; // L'elenco collegato creato sarà // 2->5->7->8->10 push(&head, 2); spingere(&testa, 5); spingere(&testa, 7); spingere(&testa, 8); spingi(&testa, 10); printf('Elenco prima della cancellazione: '); stampaLista(testa); deleteNodo(&testa, 7); printf('Elenco dopo la cancellazione: '); stampaLista(testa); restituire 0; }>
Giava // Java program to delete a given key from // linked list. import java.io.*; import java.util.*; public class GFG { /* structure for a node */ static class Node { int data; Node next; }; /* Function to insert a node at the beginning of a Circular linked list */ static Node push(Node head_ref, int data) { // Create a new node and make head as next // of it. Node ptr1 = new Node(); ptr1.data = data; ptr1.next = head_ref; /* If linked list is not null then set the next of last node */ if (head_ref != null) { // Find the node before head and update // next of it. Node temp = head_ref; while (temp.next != head_ref) temp = temp.next; temp.next = ptr1; } else ptr1.next = ptr1; /*For the first node */ head_ref = ptr1; return head_ref; } /* Function to print nodes in a given circular linked list */ static void printList(Node head) { Node temp = head; if (head != null) { do { System.out.printf('%d ', temp.data); temp = temp.next; } while (temp != head); } System.out.printf('
'); } /* Function to delete a given node from the list */ static Node deleteNode(Node head, int key) { if (head == null) return null; int flag = 0; // Find the required node Node curr = head, prev = new Node(); while (curr.data != key) { if (curr.next == head) { System.out.printf( 'Given node is not found in the list!!!
'); flag = 1; break; } prev = curr; curr = curr.next; } // Check if the element is not present in the list if (flag == 1) return head; // Check if node is only node if (curr == head && curr.next == head) { head = null; return head; } // If more than one node, check if // it is first node if (curr == head) { prev = head; while (prev.next != head) prev = prev.next; head = curr.next; prev.next = head; } // check if node is last node else if (curr.next == head) { prev.next = head; } else { prev.next = curr.next; } return head; } /* Driver code */ public static void main(String args[]) { /* Initialize lists as empty */ Node head = null; /* Created linked list will be 2.5.7.8.10 */ head = push(head, 2); head = push(head, 5); head = push(head, 7); head = push(head, 8); head = push(head, 10); System.out.printf('List Before Deletion: '); printList(head); head = deleteNode(head, 7); System.out.printf('List After Deletion: '); printList(head); } } // This code is contributed by Susobhan Akhuli>
C# using System; // Structure for a node public class Node { public int data; public Node next; } // Class for Circular Linked List public class CircularLinkedList { // Function to insert a node at the // beginning of a Circular linked list public static void Push(ref Node head_ref, int data) { // Create a new node and make head // as next of it. Node ptr1 = new Node(); ptr1.data = data; ptr1.next = head_ref; // If linked list is not NULL then // set the next of last node if (head_ref != null) { // Find the node before head and // update next of it. Node temp = head_ref; while (temp.next != head_ref) temp = temp.next; temp.next = ptr1; } else // For the first node ptr1.next = ptr1; head_ref = ptr1; } // Function to print nodes in a given // circular linked list public static void PrintList(Node head) { Node temp = head; if (head != null) { do { Console.Write(temp.data + ' '); temp = temp.next; } while (temp != head); } Console.WriteLine(); } // Function to delete a given node // from the list public static void DeleteNode(ref Node head, int key) { // If linked list is empty if (head == null) return; // If the list contains only a // single node if (head.data == key && head.next == head) { head = null; return; } Node last = head, d; // If head is to be deleted if (head.data == key) { // Find the last node of the list while (last.next != head) last = last.next; // Point last node to the next of // head i.e. the second node // of the list last.next = head.next; head = last.next; return; } // Either the node to be deleted is // not found or the end of list // is not reached while (last.next != head && last.next.data != key) { last = last.next; } // If node to be deleted was found if (last.next.data == key) { d = last.next; last.next = d.next; } else Console.WriteLine( 'Given node is not found in the list!!!'); } // Driver code public static void Main() { // Initialize lists as empty Node head = null; // Created linked list will be // 2->5->7->8->10 Spingi(testa di riferimento, 2); Spingi(rif testa, 5); Spingere(rif testa, 7); Spingi(rif testa, 8); Spingere(rif testa, 10); Console.Write('Elenco prima dell'eliminazione: '); StampaLista(testa); EliminaNodo(ref testa, 7); Console.Write('Elenco dopo l'eliminazione: '); StampaLista(testa); } }>
Javascript // Javascript program to delete a given key from linked list. // Structure for a node class Node { constructor() { this.data; this.next; } } // Function to insert a node at the // beginning of a Circular linked list function push(head, data) { // Create a new node and make head // as next of it. var ptr1 = new Node(); ptr1.data = data; ptr1.next = head; // If linked list is not NULL then // set the next of last node if (head != null) { // Find the node before head and // update next of it. let temp = head; while (temp.next != head) temp = temp.next; temp.next = ptr1; } // For the first node else ptr1.next = ptr1; head = ptr1; return head; } // Function to print nodes in a given // circular linked list function printList(head) { let tempp = head; if (head != null) { do { console.log(tempp.data); tempp = tempp.next; } while (tempp != head); } } // Function to delete a given node // from the list function deleteNode(head, key) { // If linked list is empty if (head == null) return; // If the list contains only a // single node if (head.data == key && head.next == head) { head = null; return; } let last = head; // If head is to be deleted if (head.data == key) { // Find the last node of the list while (last.next != head) last = last.next; // Point last node to the next of // head i.e. the second node // of the list last.next = head.next; head = last.next; return; } // Either the node to be deleted is // not found or the end of list // is not reached while (last.next != head && last.next.data != key) { last = last.next; } // If node to be deleted was found if (last.next.data == key) { d = last.next; last.next = d.next; d = null; } else console.log('Given node is not found in the list!!!'); } // Driver code // Initialize lists as empty head = null; // Created linked list will be // 2->5->7->8->10 testa = spingi(testa, 2); testa = spinta(testa, 5); testa = spingi(testa, 7); testa = spinta(testa, 8); testa = spingi(testa, 10); console.log('Elenco prima dell'eliminazione: '); stampaLista(testa); deleteNodo(testa, 7); console.log('Elenco dopo l'eliminazione: '); stampaLista(testa);>
Python3 # Python program to delete a given key from linked list class Node: def __init__(self, data): self.data = data self.next = None # Function to insert a node at the # beginning of a Circular linked list def push(head, data): # Create a new node and make head as next of it. newP = Node(data) newP.next = head # If linked list is not NULL then # set the next of last node if head != None: # Find the node before head and # update next of it. temp = head while (temp.next != head): temp = temp.next temp.next = newP else: newP.next = newP head = newP return head # Function to print nodes in a given circular linked list def printList(head): if head == None: print('List is Empty') return temp = head.next print(head.data, end=' ') if (head != None): while (temp != head): print(temp.data, end=' ') temp = temp.next print() # Function to delete a given node # from the list def deleteNode(head, key): # If linked list is empty if (head == None): return # If the list contains only a # single node if (head.data == key and head.next == head): head = None return last = head # If head is to be deleted if (head.data == key): # Find the last node of the list while (last.next != head): last = last.next # Point last node to the next of # head i.e. the second node # of the list last.next = head.next head = last.next return # Either the node to be deleted is # not found or the end of list # is not reached while (last.next != head and last.next.data != key): last = last.next # If node to be deleted was found if (last.next.data == key): d = last.next last.next = d.next d = None else: print('Given node is not found in the list!!!') # Driver code # Initialize lists as empty head = None # Created linked list will be # 2->5->7->8->10 testa = spingi(testa, 2) testa = spingi(testa, 5) testa = spingi(testa, 7) testa = spingi(testa, 8) testa = spingi(testa, 10) print('Elenco prima dell'eliminazione: ') printLista(head) deleteNode(head, 7) print('Elenco dopo l'eliminazione: ') printLista(head)>
Produzione
List Before Deletion: 10 8 7 5 2 List After Deletion: 10 8 5 2>
Complessità temporale: O(N), Il caso peggiore si verifica quando l'elemento da eliminare è l'ultimo elemento e dobbiamo spostarci attraverso l'intero elenco.
Spazio ausiliario: O(1), Poiché viene utilizzato spazio aggiuntivo costante.
Vantaggi delle liste collegate circolari:
- Qualsiasi nodo può essere un punto di partenza. Possiamo percorrere l'intero elenco partendo da qualsiasi punto. Dobbiamo solo fermarci quando il primo nodo visitato viene nuovamente visitato.
- Utile per l'implementazione di una coda. A differenza di Questo implementazione, non abbiamo bisogno di mantenere due puntatori per front e posterior se utilizziamo un elenco concatenato circolare. Possiamo mantenere un puntatore all'ultimo nodo inserito e il front può sempre essere ottenuto come next of last.
- Gli elenchi circolari sono utili nelle applicazioni per scorrere ripetutamente l'elenco. Ad esempio, quando su un PC sono in esecuzione più applicazioni, è normale che il sistema operativo inserisca le applicazioni in esecuzione in un elenco e poi le scorra in modo ciclico, concedendo a ciascuna di esse un periodo di tempo per l'esecuzione e quindi facendole attendere mentre la CPU viene assegnata a un'altra applicazione. È conveniente per il sistema operativo utilizzare un elenco circolare in modo che quando raggiunge la fine dell'elenco possa scorrere in primo piano.
- Le liste circolari doppiamente collegate vengono utilizzate per l'implementazione di strutture dati avanzate come Mucchio di Fibonacci .
- L'implementazione di un elenco concatenato circolare può essere relativamente semplice rispetto ad altre strutture dati più complesse come alberi o grafici.
Svantaggi dell'elenco collegato circolare:
- Rispetto agli elenchi collegati singolarmente, gli elenchi circolari sono più complessi.
- Invertire un elenco circolare è più complicato che invertire singolarmente o due volte un elenco circolare.
- È possibile che il codice entri in un ciclo infinito se non viene gestito con attenzione.
- È più difficile trovare la fine dell'elenco e controllare il ciclo.
- Sebbene gli elenchi collegati circolari possano essere efficienti in alcune applicazioni, le loro prestazioni possono essere più lente rispetto ad altre strutture dati in alcuni casi, ad esempio quando è necessario ordinare o eseguire una ricerca nell'elenco.
- Gli elenchi collegati circolari non forniscono accesso diretto ai singoli nodi
Applicazioni degli elenchi collegati circolari:
- I giochi multiplayer lo usano per dare a ogni giocatore la possibilità di giocare.
- Un elenco collegato circolare può essere utilizzato per organizzare più applicazioni in esecuzione su un sistema operativo. Queste applicazioni vengono ripetute dal sistema operativo.
- Gli elenchi collegati circolari possono essere utilizzati nei problemi di allocazione delle risorse.
- Le liste collegate circolari sono comunemente usate per implementare buffer circolari,
- Gli elenchi collegati circolari possono essere utilizzati nella simulazione e nei giochi.
Perché una lista circolare circolare?
- Un nodo punta sempre a un altro nodo, quindi l'assegnazione NULL non è necessaria.
- Qualsiasi nodo può essere impostato come punto di partenza.
- I nodi vengono attraversati rapidamente dal primo all'ultimo.
Prossimi post: Elenco collegato circolare | Set 2 (Traversale) Elenco circolare collegato singolarmente | Inserimento Si prega di scrivere commenti se si riscontrano bug nel codice/algoritmo sopra riportato o se si trovano altri modi per risolvere lo stesso problema