រំលងទៅមាតិកា

ឧបករណ៍មើល Circular Linked List

Node ចុងក្រោយភ្ជាប់មក node ដំបូងវិញ៖ មើលរង្វង់ក្នុង memory និងរបៀបដែលប្រតិបត្តិការរក្សាភាពបិទជិត។

Links
View
Nodes: 0 Node size: 16 bytes Pointer steps: 0
  • Current node
  • New or found
  • Being deleted
  • Free memory

Each box is a node at its own memory address. The pointer field holds the address of the next node (and the previous one); the arrows show where it points.

Step 1 of 1

// tail.next is always the headinsertHead(v):  node = new Node(v)  if tail = null: node.next = node; tail = node; return  node.next = tail.next   // the old head  tail.next = node  (head is now node)insertTail(v):  node = new Node(v)   // empty list: same as insertHead  node.next = tail.next  tail.next = node  tail = nodeinsertAt(i, v):  if i = 0: insertHead(v); return  cur = tail.next; repeat i − 1 times: cur = cur.next  node = new Node(v)  node.next = cur.next  cur.next = node; if cur = tail: tail = nodedelete(v):  cur = tail.next  repeat n times: if cur.value = v: stop; cur = cur.next  if not found: return  prev.next = cur.next; fix tail if cur was tail  free cursearch(v):  cur = tail.next; i = 0  do: if cur.value = v: return i      cur = cur.next; i = i + 1  while cur ≠ tail.next; return −1reverse():  prev = tail; cur = tail.next  repeat n times    next = cur.next    cur.next = prev    prev = cur; cur = next  tail = old head (tail.next is the new head)
Circular singly linked list operations
OperationTime
Access by indexO(n)
SearchO(n)
Insert at headO(1)
Insert at tailO(1) with a tail pointer
Insert after a known nodeO(1)
Delete a known nodeO(n) to find the previous node
Extra memory per node1 pointer

Circular linked list មិនមាន NULL នៅខាងចុងទេ៖ node ចុងក្រោយចង្អុលត្រឡប់មក node ដំបូងវិញ ធ្វើឱ្យ node ទាំងអស់បង្កើតជារង្វង់។ ឧបករណ៍ visualizer នេះបង្ហាញរង្វង់ក្នុង memory ជាមួយអាសយដ្ឋានពិត និងព្រួញ រួមទាំង pointer ពី tail ត្រឡប់មក head វិញ។ កុងតាក់មួយអនុញ្ញាតឱ្យប្តូរពី circular singly linked list ទៅជា circular doubly linked list ដែល prev pointer របស់ head ក៏ចង្អុលទៅកាន់ tail ផងដែរ។

បញ្ចូលនៅ head, tail ឬ index លុប ស្វែងរក និង reverse ហើយមើលរបៀបដែលប្រតិបត្តិការនីមួយៗរក្សារង្វង់ឱ្យនៅបិទជិត។ ដោយសារ tail ចង្អុលទៅ head ការរក្សាទុកតែ tail pointer មួយគត់ផ្តល់នូវការចូលប្រើ O(1) ទៅកាន់ចុងទាំងសងខាង ដែលជាបច្ចេកទេសប្រើក្នុងការអនុវត្តជាក់ស្តែងជាច្រើន។

របៀបប្រើឧបករណ៍ ឧបករណ៍មើល Circular Linked List

  1. ជ្រើសរើសតំណភ្ជាប់ Singly ឬ Doubly។
  2. វាយបញ្ចូលតម្លៃ (និង index) រួចជ្រើសរើសប្រតិបត្តិការ។
  3. មើលព្រួញពី node ចុងក្រោយត្រឡប់ទៅកាន់ node ដំបូង និងព្រួញពណ៌ក្រហមសម្រាប់ pointer ដែលកំពុងផ្លាស់ប្តូរ។
  4. ចុចទៅមុខថយក្រោយមួយជំហានៗ ឬប្តូរទៅ List order ដើម្បីមើលរង្វង់ជាជួរដែលវិលជុំវិញ។

ហេតុអ្វីប្រើ ឧបករណ៍មើល Circular Linked List របស់ ToolOrca

  • ម៉ូដ Circular singly និង circular doubly
  • គូរការភ្ជាប់ពី tail ទៅ head ក្នុង memory
  • បញ្ចូលនៅ head, tail ឬ index លុប ស្វែងរក reverse
  • ការស្វែងរកឈប់បន្ទាប់ពីវិលបានមួយជុំពេញ
  • Pseudocode សម្រាប់ម៉ូដនីមួយៗ ជាមួយការ highlight បន្ទាត់សកម្ម
  • កូដជា C++, Java, Python និង JavaScript

របៀបដែល circular linked list ដំណើរការ

នៅក្នុង circular singly linked list នោះ next pointer របស់ node ចុងក្រោយផ្ទុកអាសយដ្ឋានរបស់ node ដំបូង។ ប្រសិនបើអ្នករក្សាទុក pointer ទៅកាន់ tail នោះ head គ្រាន់តែជា tail.next ដូច្នេះចុងទាំងសងខាងគឺនៅចម្ងាយតែមួយជំហានប៉ុណ្ណោះ៖ ការបញ្ចូលនៅ head ឬ tail គឺ O(1)។ នៅក្នុង circular doubly linked list នោះ prev pointer របស់ head ក៏ចង្អុលទៅកាន់ tail ផងដែរ។

ដោយសារគ្មាន NULL នោះ loop ត្រូវតែបញ្ឈប់តាមវិធីផ្សេង៖ អ្នកត្រូវឈប់នៅពេលអ្នកត្រឡប់មកដល់ node ដែលអ្នកបានចាប់ផ្តើម។ ការភ្លេចចំណុចនេះគឺជា bug បុរាណជាមួយ circular list ដែលបណ្តាលឱ្យមាន loop គ្មានទីបញ្ចប់។

ការរក្សារង្វង់ឱ្យបិទជិត

គ្រប់ប្រតិបត្តិការត្រូវតែរក្សារង្វង់មិនឱ្យដាច់។ ការបញ្ចូលនៅ head មានន័យថា node.next = head បន្ទាប់មក tail.next = node។ ការបញ្ចូលនៅ tail គឺដូចគ្នា បូករួមទាំងការរំកិល tail ទៅកាន់ node ថ្មី។ ការលុប node តែមួយគត់នឹងធ្វើឱ្យបញ្ជីទទេ ការលុប head ឬ tail មានន័យថាត្រូវអាប់ដេត pointer ដែលចង្អុលទៅវា។ Node តែមួយគឺចង្អុលទៅកាន់ខ្លួនវាផ្ទាល់។

កន្លែងដែលគេប្រើ circular list

Circular list ស័ក្តិសមសម្រាប់អ្វីៗដែលវិលជុំ៖ ការកំណត់ពេល CPU បែប round-robin, ការប្តូរវេនគ្នាក្នុងហ្គេម multiplayer, ចំណោទ Josephus problem, repeating playlists និង ring buffers។ ការស្វែងរក ការចូលប្រើតាម index និងការលុបតាមតម្លៃនៅតែជា O(n) ដដែល ដូច linked list ផ្សេងទៀត។

គ្រប់ visualizer នៅលើគេហទំព័រនេះដំណើរការក្នុង browser របស់អ្នកជាមួយប៊ូតុងបញ្ជាដូចគ្នា៖ ចាក់ (Play), ផ្អាក (Pause), ទៅមុខមួយជំហាន (Step), ថយក្រោយមួយជំហាន (Back) និងរបាររំកិលល្បឿន។ អ្នកក៏អាចអូសរបារទីតាំងដើម្បីផ្លាស់ទីទៅជំហានណាមួយ ឬចុចលើផ្ទាំងគំនូរហើយប្រើ Space bar និងគ្រាប់ចុចព្រួញ។

សំណួរដែលសួរញឹកញាប់

តើ circular linked list គឺជាអ្វី?

ជា linked list ដែល node ចុងក្រោយចង្អុលត្រឡប់មក node ដំបូងជំនួសឱ្យ NULL ដូច្នេះអ្នកអាចបន្តដើរជុំវិញបញ្ជីជារៀងរហូត។

តើអ្នកដឹងដោយរបៀបណាថានៅពេលណាអ្នកបានឆ្លងកាត់គ្រប់ node?

ចងចាំ node ដែលអ្នកបានចាប់ផ្តើម (ជាទូទៅគឺ head) ហើយឈប់នៅពេលដែល next pointer នាំអ្នកត្រឡប់មកកាន់វាម្តងទៀត។

ហេតុអ្វីត្រូវរក្សា tail pointer ជំនួសឱ្យ head pointer?

ពីព្រោះ tail.next គឺជា head ដូច្នេះ tail pointer តែមួយផ្តល់នូវការចូលប្រើ O(1) ទៅកាន់ចុងទាំងពីរ។ ប្រសិនបើមានតែ head pointer ការដើរទៅ tail នឹងត្រូវចំណាយពេល O(n)។

តើ Josephus problem គឺជាអ្វី?

មនុស្សឈរជារង្វង់ ហើយមនុស្សទី k ម្នាក់ៗត្រូវបានដកចេញរហូតដល់នៅសល់តែម្នាក់។ Circular linked list ដើរតួជាគំរូនៃរឿងនេះដោយផ្ទាល់៖ ដើរ k ជំហាន លុប node មួយ រួចធ្វើម្តងទៀត។