Co je kruhový propojený seznam?
The kruhový propojený seznam je propojený seznam, kde jsou všechny uzly spojeny do kruhu. V kruhovém propojeném seznamu jsou první uzel a poslední uzel vzájemně spojeny, což tvoří kruh. Na konci není NULL.
Kruhový propojený seznam
java zřetězení řetězců
Obecně existují dva typy kruhových propojených seznamů:
- Kruhový jednotlivě propojený seznam: V kruhovém Jednotlivě propojeném seznamu obsahuje poslední uzel seznamu ukazatel na první uzel seznamu. Procházíme kruhový jednotlivě propojený seznam, dokud nedosáhneme stejného uzlu, kde jsme začali. Kruhový jednotlivě propojený seznam nemá začátek ani konec. V další části žádného z uzlů není přítomna žádná hodnota null.

Reprezentace kruhového jednoduše propojeného seznamu
- Kruhový dvojitě propojený seznam: Kruhový dvojitě propojený seznam má vlastnosti jak dvojitě propojeného seznamu, tak kruhového propojeného seznamu, ve kterém jsou dva po sobě jdoucí prvky propojeny nebo spojeny předchozím a dalším ukazatelem a poslední uzel ukazuje na první uzel dalším ukazatelem a také první uzel ukazuje na poslední uzel předchozím ukazatelem.

Reprezentace kruhového dvojitě propojeného seznamu
Poznámka: K reprezentaci fungování kruhového propojeného seznamu budeme používat jednoduchý kruhový propojený seznam.
Reprezentace kruhového propojeného seznamu:
Kruhové propojené seznamy jsou podobné jako jednotlivé propojené seznamy s výjimkou připojení posledního uzlu k prvnímu uzlu.
Reprezentace uzlů kruhového propojeného seznamu:
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; };>
Jáva 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->data = $data; $this->next = null; } }>
Python3 # Class Node, similar to the linked list class Node: def __init__(self,data): self.data = data self.next = None>
Příklad kruhového samostatně propojeného seznamu:

Příklad kruhového propojeného seznamu
Výše uvedený kruhový jednotlivě propojený seznam může být reprezentován jako:
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->další = dva; dva->další = tři; tři->další = jedna;>
Jáva // 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->další = $dva; $dva->další = $tři; $tři->další = $jedna;>
Python3 # Initialize the Nodes. one = Node(3) two = Node(5) three = Node(9) # Connect nodes one.next = two two.next = three three.next = one>
Vysvětlení: Ve výše uvedeném programu jsou jedna, dvě a tři uzel s hodnotami 3, 5 a 9, které jsou spojeny kruhovým způsobem jako:
- Pro uzel jedna: Ukazatel Next ukládá adresu uzlu dva.
- Pro uzel 2: Další ukládá adresu uzlu tři
- Pro uzel 3: The Další body na uzel jedna.
Operace na kruhovém propojeném seznamu:
Na kruhovém propojeném seznamu můžeme provádět některé operace podobné jednoduše propojenému seznamu, které jsou:
csma a csma cd
- Vložení
- Vymazání
1. Vložení do kruhového propojeného seznamu:
Uzel lze přidat třemi způsoby:
- Vložení na začátek seznamu
- Vložení na konec seznamu
- Vložení mezi uzly
1) Vložení na začátek seznamu: Chcete-li vložit uzel na začátek seznamu, postupujte takto:
- Vytvořte uzel, řekněte T.
- Udělejte T -> další = poslední -> další.
- poslední -> další = T.

Kruhový propojený seznam před vložením
A pak,

Kruhový propojený seznam po vložení
2) Vložení na konec seznamu: Chcete-li vložit uzel na konec seznamu, postupujte takto:
- Vytvořte uzel, řekněte T.
- Make T -> next = last -> next;
- poslední -> další = T.
- poslední = T.
Před vložením,

Kruhový propojený seznam před vložením uzlu na konec
linkedlist a arraylist
Po vložení,

Kruhový propojený seznam po vložení uzlu na konec
3) Vložení mezi uzly: Chcete-li vložit uzel mezi dva uzly, postupujte takto:
- Vytvořte uzel, řekněte T.
- Vyhledejte uzel, za který je třeba vložit T, řekněme, že uzel je P.
- Make T -> next = P -> next;
- P -> další = T.
Předpokládejme, že za uzel má hodnotu 10 je třeba vložit 12,

Kruhový propojený seznam před vložením
Po vyhledání a vložení,

Kruhový propojený seznam po vložení
jak zjistit, zda vás někdo zablokoval na Androidu
2. Odstranění v kruhovém propojeném seznamu:
1) Odstraňte uzel pouze v případě, že se jedná o jediný uzel v kruhovém propojeném seznamu:
- Uvolněte paměť uzlu
- Poslední hodnota by měla být NULL Uzel vždy ukazuje na jiný uzel, takže přiřazení NULL není nutné.
Jako výchozí bod lze nastavit libovolný uzel.
Uzly se procházejí rychle od prvního k poslednímu.
2) Odstranění posledního uzlu:
- Najděte uzel před posledním uzlem (ať je to temp)
- Udržujte adresu uzlu vedle posledního uzlu v temp
- Vymažte poslední paměť
- Na konci dejte teplotu
3) Odstraňte libovolný uzel z kruhového propojeného seznamu: Dostaneme uzel a naším úkolem je odstranit tento uzel z kruhového propojeného seznamu.
Algoritmus:
Případ 1 : Seznam je prázdný.
- Pokud je seznam prázdný, jednoduše se vrátíme.
Případ 2 :Seznam není prázdný
jednoduchý program python
- Pokud seznam není prázdný, definujeme dva ukazatele curr a předchozí a inicializujte ukazatel curr s hlava uzel.
- Procházejte seznam pomocí curr najít uzel, který má být odstraněn, a před přechodem na curr k dalšímu uzlu pokaždé nastavit prev = curr.
- Pokud je uzel nalezen, zkontrolujte, zda se nejedná o jediný uzel v seznamu. Pokud ano, nastavte head = NULL a free(curr).
- Pokud má seznam více než jeden uzel, zkontrolujte, zda se nejedná o první uzel seznamu. Podmínka pro kontrolu (curr == hlava). Pokud ano, přesuňte se na předchozí, dokud nedosáhne posledního uzlu. Poté, co prev dosáhne posledního uzlu, nastavte head = head -> next a prev -> next = head. Smazat curr.
- Pokud curr není první uzel, zkontrolujeme, zda je to poslední uzel v seznamu. Podmínka pro ověření je (curr -> next == head).
- Pokud je curr poslední uzel. Nastavíme prev -> next = head a odstraníme uzel curr pomocí free(curr).
- Pokud uzel, který se má odstranit, není ani první, ani poslední, pak nastavte prev -> next = curr -> next a odstraňte curr.
- Pokud uzel není v seznamu přítomen, vraťte hlavu a nic nedělejte.
Níže je uvedena implementace výše uvedeného přístupu:
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->data = data; ptr1->dalsi = *odkaz_hlavy; // Pokud propojený seznam není NULL, pak // nastaví další z posledního uzlu if (*head_ref != NULL) { // Najde uzel před head a // aktualizuje další uzel. Node* temp = *head_ref; while (temp->next != *head_ref) temp = temp->next; temp->dalsi = ptr1; } else // Pro první uzel ptr1->next = ptr1; *odkaz_hlavy = ptr1; } // Funkce pro tisk uzlů v daném // kruhovém propojeném seznamu void printList(Node* head) { Node* temp = head; if (head != NULL) { do { cout<< temp->data<< ' '; temp = temp->další; } while (temp != hlava); } 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)->data == klíč && (*hlavička)->další == *hlavička) { free(*hlavička); *hlava = NULL; vrátit se; } Uzel *posledni = *hlava, *d; // Pokud má být hlavička smazána if ((*head)->data == klíč) { // Najít poslední uzel seznamu while (last->next != *head) last = last->next; // Ukaž poslední uzel na další z // head tj. druhý uzel // seznamu last->next = (*head)->next; zdarma(*hlava); *hlava = poslední->další; vrátit se; } // Buď uzel, který má být odstraněn, // nenalezen, nebo konec seznamu // není dosažen, zatímco (poslední->další != *head && poslední->další->data != klíč) { poslední = poslední ->další; } // Pokud byl nalezen uzel k odstranění if (poslední->další->data == klíč) { d = poslední->další; poslední->další = d->další; volný(d); } jinak 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 push(&head, 2); push(&head, 5); push(&head, 7); push(&head, 8); push(&head, 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->data = data; ptr1->další = *odkaz_hlavy; // Pokud propojený seznam není NULL, pak // nastaví další z posledního uzlu if (*head_ref != NULL) { // Najde uzel před head a // aktualizuje další uzel. struct Node* temp = *head_ref; while (temp->next != *head_ref) temp = temp->next; temp->dalsi = ptr1; } else // Pro první uzel ptr1->next = ptr1; *odkaz_hlavy = ptr1; } // Funkce pro tisk uzlů v daném // kruhovém propojeném seznamu void printList(struct Node* head) { struct Node* temp = head; if (head != NULL) { do { printf('%d ', temp->data); temp = temp->další; } while (temp != hlava); } printf('
'); } // Funkce pro smazání daného uzlu // ze seznamu void deleteNode(struct Node** head, klíč int) { // Pokud je propojený seznam prázdný if (*head == NULL) return; // Pokud seznam obsahuje pouze // jediný uzel if ((*head)->data == klíč && (*head)->next == *head) { free(*head); *hlava = NULL; vrátit se; } struct Uzel *posledni = *hlava, *d; // Pokud má být hlavička smazána if ((*head)->data == klíč) { // Najít poslední uzel seznamu while (last->next != *head) last = last->next; // Ukaž poslední uzel na další z // head tj. druhý uzel // seznamu last->next = (*head)->next; zdarma(*hlava); *hlava = poslední->další; vrátit se; } // Buď uzel, který má být odstraněn, // nenalezen, nebo konec seznamu // není dosažen, zatímco (poslední->další != *head && poslední->další->data != klíč) { poslední = poslední ->další; } // Pokud byl nalezen uzel k odstranění if (poslední->další->data == klíč) { d = poslední->další; poslední->další = d->další; volný(d); } else printf('Daný uzel nebyl v seznamu nalezen!!!
'); } // Kód ovladače int main() { // Inicializuje seznamy jako prázdnou strukturu Node* head = NULL; // Vytvořený propojený seznam bude // 2->5->7->8->10 push(&head, 2); push(&head, 5); push(&head, 7); push(&head, 8); push(&head, 10); printf('Seznam před smazáním: '); printList(head); deleteNode(&head, 7); printf('Seznam po smazání: '); printList(head); návrat 0; }>
Jáva // 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 Push(ref head, 2); Push(ref head, 5); Push(ref head, 7); Push(ref head, 8); Push(ref head, 10); Console.Write('Seznam před smazáním: '); PrintList(head); DeleteNode(ref head, 7); Console.Write('Seznam po smazání: '); PrintList(head); } }>
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 hlava = push(head, 2); hlava = tlačit(hlava, 5); hlava = tlačit(hlava, 7); hlava = tlačit(hlava, 8); hlava = tlačit(hlava, 10); console.log('Seznam před smazáním: '); printList(head); deleteNode(head, 7); console.log('Seznam po smazání: '); printList(head);>
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 hlava = tlačit (hlava, 2) hlava = tlačit (hlava, 5) hlava = tlačit (hlava, 7) hlava = tlačit (hlava, 8) hlava = tlačit (hlava, 10) print('Seznam před smazáním: ') printList(head) deleteNode(head, 7) print('Seznam po vymazání: ') printList(head)>
Výstup
List Before Deletion: 10 8 7 5 2 List After Deletion: 10 8 5 2>
Časová náročnost: O(N), Nejhorší případ nastane, když prvek, který má být odstraněn, je posledním prvkem a my potřebujeme procházet celým seznamem.
Pomocný prostor: O(1), je použit konstantní prostor navíc.
Výhody kruhových propojených seznamů:
- Každý uzel může být výchozím bodem. Celý seznam můžeme procházet tak, že začneme z libovolného bodu. Jen se musíme zastavit, když se znovu navštíví první navštívený uzel.
- Užitečné pro implementaci fronty. Na rozdíl od tento Pokud použijeme kruhový propojený seznam, nepotřebujeme udržovat dva ukazatele pro přední a zadní část. Můžeme udržovat ukazatel na poslední vložený uzel a přední lze vždy získat jako další před posledním.
- Kruhové seznamy jsou užitečné v aplikacích k opakovanému procházení seznamu. Například, když na počítači běží více aplikací, je běžné, že operační systém zařadí spuštěné aplikace do seznamu a poté je cyklicky projde, přičemž každé z nich poskytne určitý čas na spuštění a poté je nechá chvíli čekat. CPU je předán jiné aplikaci. Pro operační systém je vhodné používat kruhový seznam, takže když se dostane na konec seznamu, může se pohybovat na začátku seznamu.
- Kruhové dvojitě propojené seznamy se používají k implementaci pokročilých datových struktur, jako je např Fibonacciho halda .
- Implementace kruhového propojeného seznamu může být relativně snadná ve srovnání s jinými složitějšími datovými strukturami, jako jsou stromy nebo grafy.
Nevýhody kruhového propojeného seznamu:
- Ve srovnání s jednoduše propojenými seznamy jsou kruhové seznamy složitější.
- Obrácení kruhového seznamu je složitější než jednoduché nebo dvojité obrácení kruhového seznamu.
- Je možné, že kód přejde do nekonečné smyčky, pokud s ním není zacházeno opatrně.
- Je těžší najít konec seznamu a ovládat smyčku.
- Přestože kruhové propojené seznamy mohou být v určitých aplikacích efektivní, jejich výkon může být v určitých případech pomalejší než u jiných datových struktur, například když je třeba seznam seřadit nebo prohledat.
- Kruhové propojené seznamy neposkytují přímý přístup k jednotlivým uzlům
Aplikace kruhových propojených seznamů:
- Hry pro více hráčů to využívají k tomu, aby každý hráč dostal šanci hrát.
- Kruhový propojený seznam lze použít k uspořádání více spuštěných aplikací v operačním systému. Tyto aplikace jsou iterovány OS.
- Při problémech s alokací zdrojů lze použít kruhové propojené seznamy.
- Kruhové propojené seznamy se běžně používají k implementaci kruhových vyrovnávacích pamětí,
- Kruhové propojené seznamy lze použít při simulaci a hraní her.
Proč kruhový propojený seznam?
- Uzel vždy ukazuje na jiný uzel, takže přiřazení NULL není nutné.
- Jako výchozí bod lze nastavit libovolný uzel.
- Uzly se procházejí rychle od prvního k poslednímu.
Další příspěvky: Circular Linked List | Sada 2 (Traversal) Circular Single Linked List | Vložení Napište prosím komentáře, pokud najdete nějakou chybu ve výše uvedeném kódu/algoritmu, nebo najděte jiné způsoby, jak vyřešit stejný problém