Ce este lista circulară legată?
The listă circulară legată este o listă legată în care toate nodurile sunt conectate pentru a forma un cerc. Într-o listă circulară legată, primul nod și ultimul nod sunt conectate unul cu celălalt, ceea ce formează un cerc. Nu există nici un NULL la sfârșit.
Listă circulară legată
În general, există două tipuri de liste circulare legate:
- Listă circulară legată individual: Într-o listă circulară legată individual, ultimul nod al listei conține un indicator către primul nod al listei. Parcurgem lista circulară legată individual până ajungem la același nod de unde am început. Lista circulară legată individual nu are început sau sfârșit. Nu este prezentă nicio valoare nulă în următoarea parte a niciunuia dintre noduri.

Reprezentarea listei circulare legate individual
- Listă circulară dublu legată: Lista circulară dublu legată are proprietăți atât ale listei dublu legate, cât și ale listei circulare legate în care două elemente consecutive sunt legate sau conectate prin indicatorul anterior și următorul, iar ultimul nod indică primul nod prin indicatorul următor și, de asemenea, primul nod indică către ultimul nod de indicatorul anterior.

Reprezentarea listei circulare dublu legate
Notă: Vom folosi lista de legătură circulară individuală pentru a reprezenta funcționarea listei de legătură circulară.
Reprezentarea listei circulare legate:
Listele legate circulare sunt similare listelor legate unice, cu excepția conectării ultimului nod la primul nod.
Reprezentarea nodului unei liste circulare legate:
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; };>
Java 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->date = $date; $this->next = null; } }>>>Python3Exemplu de listă circulară legată individual: 
Exemplu de listă circulară legată
Lista circulară de mai sus poate fi reprezentată ca:
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->următorul = doi; doi->next = trei; trei->next = unu;>>>
Java 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->următorul = $două; $două->next = $trei; $trei->next = $unu;>>>Python3 Explicaţie: În programul de mai sus, unu, doi și trei sunt nodurile cu valorile 3, 5 și, respectiv, 9, care sunt conectate într-o manieră circulară ca: - Pentru nodul unu: Indicatorul Următorul stochează adresa nodului doi.
- Pentru nodul doi: Next stochează adresa nodului trei
- Pentru nodul trei: The Următorul arată către nodul unu.
Operațiuni pe lista circulară legată:
Putem face câteva operațiuni pe lista circulară legată similară listei cu legături unice care sunt:
- Inserare
- Ștergere
1. Inserarea în lista circulară legată:
Un nod poate fi adăugat în trei moduri:
- Inserare la începutul listei
- Inserare la sfârșitul listei
- Inserție între noduri
1) Inserarea la începutul listei: Pentru a insera un nod la începutul listei, urmați acești pași:
instanță de
- Creați un nod, spuneți T.
- Faceți T -> următorul = ultimul -> următorul.
- ultimul -> următorul = T.

Listă circulară legată înainte de inserare
Și apoi,

Listă circulară legată după inserare
2) Inserare la sfarsitul listei: Pentru a insera un nod la sfârșitul listei, urmați acești pași:
- Creați un nod, spuneți T.
- Faceți T -> următorul = ultimul -> următorul;
- ultimul -> următorul = T.
- ultimul = T.
Înainte de inserare,
convertiți data în șir

Listă circulară legată înainte de inserarea nodului la sfârșit
După introducere,

Listă circulară legată după inserarea nodului la sfârșit
3) Inserarea intre noduri: Pentru a insera un nod între cele două noduri, urmați acești pași:
- Creați un nod, spuneți T.
- Căutați nodul după care trebuie inserat T, spuneți că nodul este P.
- Faceți T -> următorul = P -> următorul;
- P -> următorul = T.
Să presupunem că 12 trebuie inserat după ce nodul are valoarea 10,

Listă circulară legată înainte de inserare
După căutare și inserare,

Listă circulară legată după inserare
2. Ștergere într-o listă circulară legată:
1) Ștergeți nodul numai dacă este singurul nod din lista circulară legată:
- Eliberați memoria nodului
- Ultima valoare ar trebui să fie NULL. Un nod indică întotdeauna către un alt nod, deci nu este necesară atribuirea NULL.
Orice nod poate fi setat ca punct de plecare.
Nodurile sunt parcurse rapid de la primul la ultimul.
2) Ștergerea ultimului nod:
- Localizați nodul înainte de ultimul nod (să fie temp)
- Păstrați adresa nodului lângă ultimul nod în temp
- Ștergeți ultima memorie
- Pune temperatura la final
3) Ștergeți orice nod din lista circulară legată: Ni se va da un nod și sarcina noastră este să ștergem acel nod din lista circulară legată.
Algoritm:
Cazul 1 : Lista este goală.
- Dacă lista este goală, ne vom întoarce pur și simplu.
Cazul 2 :Lista nu este goală
- Dacă lista nu este goală, definim doi pointeri curr și prev și inițializați indicatorul curr cu cap nodul.
- Parcurgeți lista folosind curr pentru a găsi nodul de șters și înainte de a trece la curr la următorul nod, de fiecare dată setați prev = curr.
- Dacă nodul este găsit, verificați dacă este singurul nod din listă. Dacă da, setați head = NULL și free(curr).
- Dacă lista are mai multe noduri, verificați dacă este primul nod al listei. Condiție pentru a verifica acest lucru (curr == cap). Dacă da, atunci mutați prev până ajunge la ultimul nod. După ce prev ajunge la ultimul nod, setați head = head -> next și prev -> next = head. Șterge curr.
- Dacă curr nu este primul nod, verificăm dacă este ultimul nod din listă. Condiția pentru a verifica acest lucru este (curr -> next == head).
- Dacă curr este ultimul nod. Setați prev -> next = head și ștergeți nodul curr prin free(curr).
- Dacă nodul de șters nu este nici primul, nici ultimul nod, atunci setați prev -> next = curr -> next și delete curr.
- Dacă nodul nu este prezent în listă, returnați capul și nu faceți nimic.
Mai jos este implementarea abordării de mai sus:
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->date = date; ptr1->next = *head_ref; // Dacă lista legată nu este NULL, atunci // setează următorul din ultimul nod if (*head_ref != NULL) { // Găsiți nodul înainte de cap și // actualizați următorul. Nod* temp = *head_ref; while (temp->next != *head_ref) temp = temp->next; temp->next = ptr1; } else // Pentru primul nod ptr1->next = ptr1; *head_ref = ptr1; } // Funcție de imprimare a nodurilor dintr-o listă circulară // dată void printList(Nod* head) { Node* temp = head; if (cap != NULL) { do { cout<< temp->date<< ' '; temp = temp->Următorul; } while (temp != cap); } 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)->date == cheie && (*head)->next == *head) { liber(*head); *cap = NULL; întoarcere; } Nodul *last = *head, *d; // Dacă head va fi șters if ((*head)->data == key) { // Găsiți ultimul nod al listei în timp ce (last->next != *head) last = last->next; // Punctează ultimul nod către următorul // cap, adică al doilea nod // al listei last->next = (*head)->next; liber(*cap); *cap = ultimul->next; întoarcere; } // Fie nodul de șters // nu este găsit, fie la sfârșitul listei // nu este atins în timp ce (last->next != *head && last->next->data != key) { last = last ! ->urmatorul; } // Dacă nodul de șters a fost găsit if (last->next->data == key) { d = last->next; last->next = d->next; liber(d); } else 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 împingere(&cap, 2); împinge(&cap, 5); împinge(&cap, 7); împinge(&cap, 8); împinge(&cap, 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->date = date; ptr1->next = *head_ref; // Dacă lista legată nu este NULL, atunci // setează următorul din ultimul nod if (*head_ref != NULL) { // Găsiți nodul înainte de cap și // actualizați următorul. struct Node* temp = *head_ref; while (temp->next != *head_ref) temp = temp->next; temp->next = ptr1; } else // Pentru primul nod ptr1->next = ptr1; *head_ref = ptr1; } // Funcție de tipărire a nodurilor dintr-o listă circulară // dată void printList(struct Node* head) { struct Node* temp = head; if (head != NULL) { do { printf('%d ', temp->data); temp = temp->next; } while (temp != cap); } printf('
'); } // Funcție de ștergere a unui nod dat // din listă void deleteNode(struct Node** head, int key) { // Dacă lista legată este goală dacă (*head == NULL) return; // Dacă lista conține doar un // un singur nod if ((*head)->data == key && (*head)->next == *head) { free(*head); *cap = NULL; întoarcere; } struct Node *last = *head, *d; // Dacă head va fi șters if ((*head)->data == key) { // Găsiți ultimul nod al listei în timp ce (last->next != *head) last = last->next; // Punctează ultimul nod către următorul // cap, adică al doilea nod // al listei last->next = (*head)->next; liber(*cap); *cap = ultimul->next; întoarcere; } // Fie nodul de șters // nu este găsit, fie la sfârșitul listei // nu este atins în timp ce (last->next != *head && last->next->data != key) { last = last ! ->urmatorul; } // Dacă nodul de șters a fost găsit if (last->next->data == key) { d = last->next; last->next = d->next; liber(d); } else printf('Nodul dat nu este găsit în listă!!!
'); } // Cod driver int main() { // Initializeaza liste ca struct goale Node* head = NULL; // Lista legată creată va fi // 2->5->7->8->10 push(&head, 2); împinge(&cap, 5); împinge(&cap, 7); împinge(&cap, 8); împinge(&cap, 10); printf('Lista înainte de ștergere: '); printList(cap); deleteNode(&head, 7); printf('Lista după ștergere: '); printList(cap); întoarce 0; }>>>
Java
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 Push(ref cap, 2); Împingeți (cap ref, 5); Împingeți (cap ref, 7); Împingeți (cap ref, 8); Împingeți (cap ref, 10); Console.Write('Lista înainte de ștergere: '); PrintList(cap); DeleteNode(cap ref, 7); Console.Write('Lista după ștergere: '); PrintList(cap); } }>>>Javascript5->7->8->10 cap = împingere(cap, 2); cap = împinge(cap, 5); cap = împinge(cap, 7); cap = împinge(cap, 8); cap = împingere(cap, 10); console.log('Lista înainte de ștergere: '); printList(cap); deleteNode(cap, 7); console.log('Lista după ștergere: '); printList(cap);>>> Python35->7->8->10 cap = împinge(cap, 2) cap = împinge(cap, 5) cap = împinge(cap, 7) cap = împinge(cap, 8) cap = împinge(cap, 10) print('Lista înainte de ștergere: ') printList(head) deleteNode(head, 7) print('List After Deletion: ') printList(head)>
Ieșire
List Before Deletion: 10 8 7 5 2 List After Deletion: 10 8 5 2>
Complexitatea timpului: O(N), Cel mai rău caz apare atunci când elementul de șters este ultimul element și trebuie să trecem prin întreaga listă.
Spațiu auxiliar: O(1), ca spațiu suplimentar constant este utilizat.
Avantajele listelor circulare legate:
- Orice nod poate fi un punct de plecare. Putem parcurge întreaga listă pornind din orice punct. Trebuie doar să ne oprim atunci când primul nod vizitat este vizitat din nou.
- Util pentru implementarea unei cozi. Spre deosebire de acest implementare, nu trebuie să menținem două indicatori pentru față și spate dacă folosim o listă circulară legată. Putem menține un pointer către ultimul nod inserat și partea din față poate fi întotdeauna obținută ca următorul ultimul.
- Listele circulare sunt utile în aplicații pentru a parcurge lista în mod repetat. De exemplu, atunci când mai multe aplicații rulează pe un PC, este obișnuit ca sistemul de operare să pună aplicațiile care rulează într-o listă și apoi să le parcurgă, oferindu-le fiecăreia o porțiune de timp pentru a le executa și apoi făcându-le să aștepte în timp ce CPU-ul este dat unei alte aplicații. Este convenabil ca sistemul de operare să folosească o listă circulară, astfel încât, atunci când ajunge la sfârșitul listei, să poată trece la începutul listei.
- Listele circulare dublu legate sunt utilizate pentru implementarea structurilor avansate de date precum Heap Fibonacci .
- Implementarea unei liste circulare conectate poate fi relativ ușoară în comparație cu alte structuri de date mai complexe, cum ar fi arbori sau grafice.
Dezavantajele listei circulare legate:
- În comparație cu listele cu legături unice, listele circulare sunt mai complexe.
- Inversarea unei liste circulare este mai complicată decât inversarea individuală sau dublă a unei liste circulare.
- Este posibil ca codul să intre într-o buclă infinită dacă nu este tratat cu atenție.
- Este mai greu să găsești sfârșitul listei și să controlezi bucla.
- Deși listele legate circulare pot fi eficiente în anumite aplicații, performanța lor poate fi mai lentă decât alte structuri de date în anumite cazuri, cum ar fi atunci când lista trebuie sortată sau căutată.
- Listele circulare legate nu oferă acces direct la nodurile individuale
Aplicații ale listelor circulare legate:
- Jocurile multiplayer folosesc acest lucru pentru a oferi fiecărui jucător șansa de a juca.
- O listă circulară legată poate fi utilizată pentru a organiza mai multe aplicații care rulează pe un sistem de operare. Aceste aplicații sunt repetate de sistemul de operare.
- Listele circulare legate pot fi utilizate în problemele de alocare a resurselor.
- Listele circulare legate sunt utilizate în mod obișnuit pentru a implementa buffer-uri circulare,
- Listele circulare legate pot fi folosite în simulare și jocuri.
De ce o listă circulară legată?
- Un nod indică întotdeauna către un alt nod, deci nu este necesară atribuirea NULL.
- Orice nod poate fi setat ca punct de plecare.
- Nodurile sunt parcurse rapid de la primul la ultimul.
Postările următoare: Listă circulară legată | Setul 2 (Traversare) Listă circulară legată individual | Inserare Vă rugăm să scrieți comentarii dacă găsiți vreo eroare în codul/algoritmul de mai sus sau găsiți alte modalități de a rezolva aceeași problemă