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

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

មើល node រាយប៉ាយក្នុង memory ភ្ជាប់គ្នាដោយ next pointer និងមើលរាល់ការផ្លាស់ប្តូរ pointer។

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; the arrows show where it points.

Step 1 of 1

insertHead(v):  node = new Node(v)  node.next = head  head = nodeinsertTail(v):  node = new Node(v)  if head = null: head = node; return  cur = head  while cur.next ≠ null: cur = cur.next  cur.next = nodeinsertAt(i, v):  if i = 0: insertHead(v); return  cur = head; repeat i − 1 times: cur = cur.next  node = new Node(v)  node.next = cur.next  cur.next = nodedelete(v):  if head.value = v: head = head.next; return  prev = head  while prev.next ≠ null and prev.next.value ≠ v: prev = prev.next  if prev.next = null: return   // not found  prev.next = prev.next.next  free the removed nodesearch(v):  cur = head; i = 0  while cur ≠ null: if cur.value = v: return i    cur = cur.next; i = i + 1  return −1reverse():  prev = null; cur = head  while cur ≠ null    next = cur.next    cur.next = prev    prev = cur; cur = next  head = prev
Singly linked list operations
OperationTime
Access by indexO(n)
SearchO(n)
Insert at headO(1)
Insert at tailO(n) (O(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

Singly linked list ផ្ទុកតម្លៃនីមួយៗក្នុង node ផ្ទាល់ខ្លួន ហើយ node នីមួយៗផ្ទុកអាសយដ្ឋានរបស់ node បន្ទាប់។ ឧបករណ៍ visualizer នេះបង្ហាញរូបភាពជាក់ស្តែង៖ node បង្ហាញនៅអាសយដ្ឋាន memory រាយប៉ាយ គ្រប់ node បង្ហាញអាសយដ្ឋានដែលរក្សាទុកក្នុង next field របស់វា (ឬ NULL) ហើយព្រួញបង្ហាញពីទិសដៅដែល pointer នីមួយៗចង្អុលទៅ។ ប្តូរទៅ លំដាប់បញ្ជី (List order) ដើម្បីមើល node ទាំងនោះតម្រៀបតាមលំដាប់ដែល pointer ឆ្លងកាត់។

បញ្ចូលនៅ head នៅ tail ឬនៅ index ណាមួយ លុបតម្លៃ ស្វែងរក ឬ reverse បញ្ជីទាំងមូល ហើយមើលប្រតិបត្តិការម្តងមួយ pointer ជាមួយបន្ទាត់ pseudocode ដែលត្រូវគ្នាកំពុង highlight។ ឧបករណ៍រាប់បង្ហាញចំនួនជំហាន pointer ដែលប្រតិបត្តិការនីមួយៗត្រូវការ ដើម្បីឱ្យអ្នកយល់ថាហេតុអ្វីការបញ្ចូលនៅ head គឺ O(1) ប៉ុន្តែការបញ្ចូលនៅ tail គឺ O(n) ប្រសិនបើគ្មាន tail pointer។

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

  1. វាយបញ្ចូល តម្លៃ (និង index សម្រាប់ការបញ្ចូលតាម index)។
  2. ចុច បញ្ចូលនៅ head, បញ្ចូលនៅ tail, បញ្ចូលតាម index, លុបតម្លៃ, ស្វែងរកតម្លៃ ឬ Reverse។
  3. មើលចលនា animation៖ node ពណ៌ទឹកក្រូចជាកន្លែងដែល pointer (cur ឬ prev) កំពុងស្ថិតនៅ ពណ៌បៃតងជាតម្លៃថ្មី ឬរកឃើញ ពណ៌ក្រហមកំពុងត្រូវបានលុប។ ព្រួញពណ៌ក្រហមគឺជា pointer ដែលទើបតែផ្លាស់ប្តូរ។
  4. ប្រើ ជំហានបន្ទាប់ (Step) និង ថយក្រោយ (Back) ដើម្បីមើលយឺតៗ និងប្តូររវាងទិដ្ឋភាព Memory និង List order។

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

  • ទិដ្ឋភាព Memory ជាមួយអាសយដ្ឋានពិត និង next-pointer fields
  • ទិដ្ឋភាព List-order នៃ node ដដែល
  • បញ្ចូលនៅ head, tail ឬ index លុប ស្វែងរក និង reverse
  • Pointer ដែលផ្លាស់ប្តូរត្រូវ highlight ពណ៌ក្រហម
  • Pseudocode ត្រូវ highlight តាមបន្ទាត់នីមួយៗ
  • កូដជា C++, Java, Python និង JavaScript
  • តារាង Complexity សម្រាប់គ្រប់ប្រតិបត្តិការ

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

Node នីមួយៗមានពីរផ្នែក៖ តម្លៃ និង pointer next ដែលផ្ទុកអាសយដ្ឋាន memory របស់ node បន្ទាប់។ បញ្ជីផ្ទាល់ចងចាំតែអាសយដ្ឋានរបស់ node ដំបូងប៉ុណ្ណោះ គឺ head។ Next pointer របស់ node ចុងក្រោយគឺ NULL (None ក្នុង Python, null ក្នុង Java និង JavaScript) ដែលបញ្ជាក់ពីចំណុចបញ្ចប់។

ដោយសារ node ភ្ជាប់គ្នាដោយអាសយដ្ឋាន ពួកវាអាចស្ថិតនៅកន្លែងណាក៏បានក្នុង memory។ នេះផ្ទុយស្រឡះពី array៖ គ្មានរូបមន្តដើម្បីស្វែងរក node ទី 5 នោះទេ ដូច្នេះអ្នកត្រូវចាប់ផ្តើមពី head ហើយដើរតាម 4 pointers។ ម្យ៉ាងវិញទៀត ការបន្ថែម node មិនដែលរំកិល node ផ្សេងទៀតឡើយ។ អ្នកគ្រាន់តែប្តូរ pointer មួយ ឬពីរតែប៉ុណ្ណោះ។

ការបញ្ចូល ការលុប និង reverse មួយជំហានម្តងៗ

បញ្ចូលនៅ head៖ បង្កើត node កំណត់ node.next = head បន្ទាប់មក head = node។ ប្តូរ pointer ពីរដង O(1)។ បញ្ចូលបន្ទាប់ពី node ណាមួយ៖ node.next = cur.next បន្ទាប់មក cur.next = node។ លំដាប់គឺសំខាន់ណាស់៖ ប្រសិនបើអ្នកសរសេរជាន់លើ cur.next មុន អ្នកនឹងបាត់បង់ផ្នែកដែលនៅសល់នៃបញ្ជី។

លុប៖ ដើរជាមួយ prev pointer រហូតដល់ prev.next មានតម្លៃដែលត្រូវលុប បន្ទាប់មកកំណត់ prev.next = prev.next.next ដើម្បីឱ្យបញ្ជីរំលង node នោះ រួច free វាចោល។ Reverse៖ ដើរកាត់បញ្ជីជាមួយ prev, cur និង next pointers ហើយបង្វិលគ្រប់ next pointer ត្រឡប់មកវិញ។ នេះជាសំណួរសម្ភាសន៍បុរាណមួយ ហើយដំណើរការក្នុងពេល O(n) ជាមួយទំហំ O(1) បន្ថែម។

តើគួរជ្រើសរើស Linked list ឬ array?

Linked list ល្អប្រសើរនៅពេលអ្នកបញ្ចូល ឬដកចេញនៅខាងមុខញឹកញាប់ នៅពេលអ្នកមាន pointer ទៅកាន់កន្លែងដែលត្រូវប្តូររួចហើយ ឬនៅពេលដែលធាតុមិនត្រូវរើក្នុង memory។ Array ល្អប្រសើរសម្រាប់ការចូលប្រើតាម index សម្រាប់ការស្វែងរកទិន្នន័យដែលបានតម្រៀបដោយ binary search និងសម្រាប់ល្បឿនក្នុងការ loop ពីព្រោះធាតុ array ស្ថិតនៅជាមួយគ្នាក្នុង CPU cache ខណៈដែល list nodes រាយប៉ាយ។

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

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

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

ជាខ្សែសង្វាក់នៃ node ដែល node នីមួយៗផ្ទុកតម្លៃ និងអាសយដ្ឋានរបស់ node បន្ទាប់។ អ្នកអាចធ្វើដំណើរទៅមុខបានតែមួយទិសប៉ុណ្ណោះ គឺពី head ទៅកាន់ NULL នៅខាងចុង។

ហេតុអ្វីការចូលប្រើធាតុទី n គឺ O(n)?

ដោយសារតែគ្មានរូបមន្តអាសយដ្ឋានដូចក្នុង array ទេ។ អ្នកត្រូវចាប់ផ្តើមពី head ហើយដើរតាម next pointers ម្តងមួយៗរហូតដល់ទីតាំង n។

តើត្រូវ reverse singly linked list យ៉ាងដូចម្តេច?

រក្សាទុក pointers បី៖ prev = null, cur = head និង next។ នៅក្នុង loop រក្សាទុក next = cur.next កំណត់ cur.next = prev បន្ទាប់មកផ្លាស់ទី prev = cur និង cur = next។ នៅពេល cur ស្មើ null នោះ prev គឺជា head ថ្មី។

ហេតុអ្វីការបញ្ចូលនៅ tail ទីនេះគឺ O(n)?

បញ្ជីនេះរក្សាទុកតែ head pointer ប៉ុណ្ណោះ ដូច្នេះវាត្រូវដើរទៅកាន់ node ចុងក្រោយសិន។ ការរក្សាទុក tail pointer ដាច់ដោយឡែកមួយធ្វើឱ្យការបញ្ចូលនៅ tail ក្លាយជា O(1) ដូចដែលមាននៅក្នុង doubly linked list visualizer។

តើ linked list ប្រើ memory ច្រើនជាង array ដែរឬទេ?

បាទ/ចាស។ Node នីមួយៗផ្ទុក pointer (8 bytes លើប្រព័ន្ធ 64-bit) បន្ថែមលើតម្លៃ ហើយ memory allocators ក៏បន្ថែម overhead ផ្ទាល់ខ្លួនសម្រាប់ node នីមួយៗផងដែរ។