Linked Lists (node တွေ ချိတ်ဆက်ထားတဲ့ list များ)
B4.1.2, B4.1.3 (HL): Evaluate linked lists. Construct and apply linked lists: singly linked (insertion, deletion, traversal, search).
မြန်မာလို: linked list (node တွေ ချိတ်ဆက်ထားတဲ့ list) တွေရဲ့ အားသာချက်နဲ့ အားနည်းချက်တွေကို ချိန်ဆပြီး အကဲဖြတ်နိုင်ရပါမယ်။ Singly linked list (တစ်ဘက်တည်း ချိတ်ဆက်ထားတဲ့ linked list) တွေကို ကိုယ်တိုင် တည်ဆောက်ပြီး အသုံးချနိုင်ရပါမယ်: insertion (ထည့်ခြင်း)၊ deletion (ဖျက်ခြင်း)၊ traversal (node တိုင်းကို အစဉ်တကျ သွားကြည့်ခြင်း) နဲ့ search (ရှာခြင်း)။
ဒီစာမျက်နှာက HL အတွက်ပဲ ဖြစ်ပါတယ်။ SL (Standard Level) နဲ့ HL (Higher Level) ဆိုတာ IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) သင်တန်းရဲ့ အဆင့်နှစ်ဆင့်ဖြစ်ပြီး HL အပိုင်းတွေက ပိုနက်နက်ရှိုင်းရှိုင်း လေ့လာရတဲ့ အပိုင်းတွေပါ။
အဓိက အယူအဆများ
Linked list ဆိုတာ node (ဒေတာ သိမ်းထားတဲ့ အကွက်) လို့ ခေါ်တဲ့ element (အစုထဲက အချက်) တွေကို တစ်ကြောင်းတည်း အစဉ်လိုက် စုထားတဲ့ collection (ဒေတာအစု) ပါ။ Node တစ်ခုစီမှာ ဒေတာနဲ့ အစဉ်ထဲက နောက် node ကို ညွှန်းတဲ့ reference (object ရှိရာ memory နေရာကို ညွှန်းတဲ့ တန်ဖိုး၊ pointer လို့လည်း ခေါ်ပါတယ်) ကို သိမ်းထားပါတယ်။ Array (အရွယ်အစား ပုံသေ၊ အမျိုးအစားတူ ဒေတာစု) နဲ့ မတူတာက element တွေကို contiguous memory (memory ထဲမှာ ဆက်တိုက် ကပ်လျက် ရှိတဲ့ နေရာ) ထဲမှာ မသိမ်းပါဘူး: node တစ်ခုစီက heap (object တွေ သိမ်းတဲ့ memory အပိုင်း) ထဲက ဘယ်နေရာမှာမဆို ရှိနိုင်ပြီး reference တွေနဲ့ပဲ ချိတ်ဆက်ထားပါတယ်။
Node (ဒေတာ သိမ်းထားတဲ့ အကွက်)
Singly linked list ထဲက node တိုင်းမှာ အပိုင်း နှစ်ပိုင်း ရှိပါတယ်:
- Data: node ထဲမှာ သိမ်းထားတဲ့ တန်ဖိုး
- Next: နောက် node ကို ညွှန်းတဲ့ reference။ နောက်ဆုံး node ဖြစ်ရင် next က
null(ဘာ object ကိုမှ မညွှန်းတဲ့ တန်ဖိုး) ဖြစ်ပါတယ်။ Python မှာတော့ ဒီအယူအဆအတွက်Noneကို သုံးပါတယ်။
public class Node {
String data;
Node next;
public Node(String data) {
this.data = data;
this.next = null;
}
}
class Node():
def __init__(self, data):
self.data = data # value stored in the node
self.next = None # no next node yet (None is Python's null)
Node class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) က self-referential (ကိုယ့် class အမျိုးအစားကိုယ် ပြန်ညွှန်းတဲ့) class ပါ: field (object ထဲက အချက်အလက် အကွက်) next ရဲ့ type က Node ဖြစ်တာကြောင့် node တစ်ခုစီက type တူတဲ့ နောက် node တစ်ခုကို ညွှန်းပါတယ်။
Head (list ရဲ့ ရှေ့ဆုံး node) နဲ့ Tail (list ရဲ့ နောက်ဆုံး node)
- Head ဆိုတာ list ထဲက ပထမဆုံး node ကို ညွှန်းတဲ့ reference ပါ။ List ကို head ကနေ တစ်ဆင့် ယူသုံးပါတယ်။
- Tail ဆိုတာ list ထဲက နောက်ဆုံး node ပါ။ သူ့ရဲ့
nextfield ကnullဖြစ်ပါတယ်။ - Empty list (ဘာ node မှ မရှိတဲ့ list) မှာ
head == nullဖြစ်ပါတယ်။
Node တစ်ခုစီက data နဲ့ next ဆိုတဲ့ အပိုင်း နှစ်ပိုင်းပါတဲ့ အကွက်ပါ။ မြှားတစ်ခုစီက next field ထဲက အစက်ကနေ စပြီး အဲဒီ field ညွှန်းထားတဲ့ node မှာ ဆုံးပါတယ်။
ပုံထဲက English စာတွေရဲ့ အဓိပ္ပာယ်: “one node” က node တစ်ခု၊ “last node (tail)” က နောက်ဆုံး node (tail) လို့ အဓိပ္ပာယ်ရပါတယ်။
အဓိက ဝေါဟာရများ
| ဝေါဟာရ | အဓိပ္ပာယ် |
|---|---|
| Node | ဒေတာနဲ့ pointer ပါတဲ့ element တစ်ခု |
| Head | ပထမဆုံး node ကို ညွှန်းတဲ့ reference |
| Tail | နောက်ဆုံး node (next က null ဖြစ်ပါတယ်) |
| Successor | Node တစ်ခုရဲ့ နောက်မှာ ရှိတဲ့ node |
| Predecessor | Node တစ်ခုရဲ့ ရှေ့မှာ ရှိတဲ့ node |
| Null pointer | ဘာကိုမှ မညွှန်းတဲ့ reference: list ရဲ့ အဆုံးကို ပြပါတယ် |
| Traversal | next reference တွေကို လိုက်ပြီး head ကနေ tail အထိ node တိုင်းကို သွားကြည့်ခြင်း |
Linked List နဲ့ Array နှိုင်းယှဉ်ချက်
| ဂုဏ်သတ္တိ | Array | Singly Linked List |
|---|---|---|
| အရွယ်အစား | ဖန်တီးချိန်မှာ ပုံသေ | Program run နေစဉ် ကြီးလာ၊ သေးသွားနိုင် |
| Memory ထဲမှာ နေရာချပုံ | ဆက်တိုက် ကပ်လျက် အပိုင်း တစ်ခု | Reference တွေနဲ့ ချိတ်ထားပြီး ဟိုဒီ ပြန့်ကျဲနေတဲ့ node တွေ |
| Index (နေရာအမှတ်) နဲ့ ယူသုံးခြင်း | O(1): တိုက်ရိုက် | O(n): head ကနေ traverse လုပ်ရပါတယ် |
| ရှေ့ဆုံးမှာ ထည့်ခြင်း | O(n): element အားလုံးကို နေရာ ရွှေ့ရပါတယ် | O(1): head reference ကို ပြင်ရုံပါပဲ |
| အဆုံးမှာ ထည့်ခြင်း | နေရာ ရှိရင် O(1) | O(n): tail အထိ traverse လုပ်ရပါတယ် (tail reference ရှိရင် O(1)) |
| ရှေ့ဆုံးကနေ ဖျက်ခြင်း | O(n): element အားလုံးကို နေရာ ရွှေ့ရပါတယ် | O(1): head reference ကို ပြင်ရုံပါပဲ |
| Element တစ်ခုစီအတွက် memory | ဒေတာ သက်သက်ပဲ | ဒေတာ + reference တစ်ခု (အပို ကုန်ကျမှု ဖြစ်တဲ့ overhead) |
အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ
ဥပမာ 1: Linked List ကို အစကနေ တည်ဆောက်ခြင်း
public class SinglyLinkedList {
private Node head;
public SinglyLinkedList() {
head = null;
}
// Add a new node to the front of the list
public void addToFront(String data) {
Node newNode = new Node(data);
newNode.next = head; // point new node to current head
head = newNode; // update head to new node
}
// Traverse and print all elements
public void printAll() {
Node current = head;
while (current != null) {
System.out.print(current.data + " -> ");
current = current.next;
}
System.out.println("null");
}
// Return the number of nodes
public int size() {
int count = 0;
Node current = head;
while (current != null) {
count++;
current = current.next;
}
return count;
}
public static void main(String[] args) {
SinglyLinkedList list = new SinglyLinkedList();
list.addToFront("Cherry");
list.addToFront("Banana");
list.addToFront("Apple");
list.printAll();
System.out.println("Size: " + list.size());
}
}
class SinglyLinkedList():
def __init__(self):
self._head = None # leading underscore = private, like Java's private modifier
# Add a new node to the front of the list
def add_to_front(self, data):
new_node = Node(data)
new_node.next = self._head # point new node to current head
self._head = new_node # update head to new node
# Traverse and print all elements
def print_all(self):
temp = self._head
while temp != None:
print(temp.data + " -> ", end="")
temp = temp.next
print("null")
# Return the number of nodes
def size(self):
count = 0
temp = self._head
while temp != None:
count = count + 1
temp = temp.next
return count
# "list" is a built-in name in Python, so the driver uses a different variable name
fruits = SinglyLinkedList()
fruits.add_to_front("Cherry")
fruits.add_to_front("Banana")
fruits.add_to_front("Apple")
fruits.print_all()
print("Size:", fruits.size())
Output (program က ထုတ်ပြတဲ့ ရလဒ်):
Apple -> Banana -> Cherry -> null
Size: 3
addToFront က ထည့်တဲ့ အစဉ်ကို ပြောင်းပြန် ဖြစ်စေတာကို သတိထားကြည့်ပါ: “Cherry” ကို အရင်ဆုံး ထည့်ခဲ့ပေမယ့် node အသစ် တစ်ခုစီကို လက်ရှိ head ရဲ့ ရှေ့မှာ ထားတာကြောင့် Cherry က tail မှာ ရောက်သွားပါတယ်။
Banana, Cherry ဆိုတဲ့ list ပေါ်မှာ addToFront("Apple")add_to_front("Apple") ကို ခေါ်ပုံပါ။ အဆင့်တိုင်းရဲ့ ခေါင်းစဉ်က အဲဒီ အဆင့်ရဲ့ code line ဖြစ်ပြီး အရောင် ထင်ရှားတဲ့ မြှားက အဲဒီ line ပြောင်းလိုက်တဲ့ reference ပါ။
လုပ်တဲ့ အစဉ်က အရေးကြီးပါတယ်။
addToFrontထဲမှာhead = newNodeလို့ head ကို မပြောင်းခင်newNode.next = headကို အရင် သတ်မှတ်ပါ။ ဒီအဆင့်တွေကို ပြောင်းပြန် လုပ်မိရင် head အဟောင်းကို ညွှန်းတဲ့ reference ပျောက်သွားပြီး သူနဲ့အတူ ကျန်တဲ့ list တစ်ခုလုံးကိုလည်း ပြန်ရောက်လို့ မရတော့ပါဘူး။
ဥပမာ 2: အဆုံးမှာ ထည့်ခြင်း၊ ရှာခြင်းနဲ့ ဖယ်ထုတ်ခြင်း
public class SinglyLinkedList {
private Node head;
public SinglyLinkedList() {
head = null;
}
public void addToFront(String data) {
Node newNode = new Node(data);
newNode.next = head;
head = newNode;
}
// Add a new node to the end of the list
public void addToEnd(String data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode; // empty list: new node becomes head
return;
}
Node current = head;
while (current.next != null) {
current = current.next; // traverse to last node
}
current.next = newNode; // link last node to new node
}
// Search for a value: return true if found
public boolean contains(String target) {
Node current = head;
while (current != null) {
if (current.data.equals(target)) {
return true;
}
current = current.next;
}
return false;
}
// Remove the first occurrence of a value
public boolean remove(String target) {
if (head == null) {
return false; // empty list
}
if (head.data.equals(target)) {
head = head.next; // remove head node
return true;
}
Node current = head;
while (current.next != null) {
if (current.next.data.equals(target)) {
current.next = current.next.next; // skip the target node
return true;
}
current = current.next;
}
return false; // not found
}
public void printAll() {
Node current = head;
while (current != null) {
System.out.print(current.data + " -> ");
current = current.next;
}
System.out.println("null");
}
public static void main(String[] args) {
SinglyLinkedList roster = new SinglyLinkedList();
roster.addToEnd("Aiko");
roster.addToEnd("Ben");
roster.addToEnd("Carlos");
roster.addToEnd("Diana");
System.out.println("Initial list:");
roster.printAll();
System.out.println("Contains Ben? " + roster.contains("Ben"));
System.out.println("Contains Eve? " + roster.contains("Eve"));
roster.remove("Ben");
System.out.println("After removing Ben:");
roster.printAll();
roster.remove("Aiko");
System.out.println("After removing Aiko (head):");
roster.printAll();
}
}
class SinglyLinkedList():
def __init__(self):
self._head = None
def add_to_front(self, data):
new_node = Node(data)
new_node.next = self._head
self._head = new_node
# Add a new node to the end of the list
def add_to_end(self, data):
new_node = Node(data)
if self._head == None:
self._head = new_node # empty list: new node becomes head
return
temp = self._head
while temp.next != None:
temp = temp.next # traverse to last node
temp.next = new_node # link last node to new node
# Search for a value: return True if found
def contains(self, target):
found = False
temp = self._head
while temp != None and found == False: # no break: the flag ends the loop
if temp.data == target: # == compares string content in Python
found = True
temp = temp.next
return found
# Remove the first occurrence of a value
def remove(self, target):
if self._head == None:
return False # empty list
if self._head.data == target:
self._head = self._head.next # remove head node
return True
temp = self._head
while temp.next != None:
if temp.next.data == target:
temp.next = temp.next.next # skip the target node
return True
temp = temp.next
return False # not found
def print_all(self):
temp = self._head
while temp != None:
print(temp.data + " -> ", end="")
temp = temp.next
print("null")
roster = SinglyLinkedList()
roster.add_to_end("Aiko")
roster.add_to_end("Ben")
roster.add_to_end("Carlos")
roster.add_to_end("Diana")
print("Initial list:")
roster.print_all()
print("Contains Ben?", roster.contains("Ben")) # Python prints True/False with a capital letter
print("Contains Eve?", roster.contains("Eve"))
roster.remove("Ben")
print("After removing Ben:")
roster.print_all()
roster.remove("Aiko")
print("After removing Aiko (head):")
roster.print_all()
Output:
Initial list:
Aiko -> Ben -> Carlos -> Diana -> null
Contains Ben? true
Contains Eve? false
After removing Ben:
Aiko -> Carlos -> Diana -> null
After removing Aiko (head):
Carlos -> Diana -> null
contains("Eve") က currenttemp ကို list တစ်လျှောက် node တစ်ခုချင်း ရွှေ့သွားပါတယ်။ Diana ပြီးနောက် currenttemp က nullNone ဖြစ်သွားလို့ loop (ထပ်ခါထပ်ခါ run တဲ့ code အပိုင်း) ပြီးဆုံးပြီး method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) က falseFalse ကို ပြန်ပေးပါတယ်။
remove အလုပ်လုပ်ပုံ:
- Head ကို ဖယ်ထုတ်ခြင်း: target (ရှာပြီး ဖယ်ထုတ်ချင်တဲ့ တန်ဖိုး) က head node ဖြစ်ရင်
head = head.nextလို့ သတ်မှတ်လိုက်ရုံပါပဲ: head အဟောင်းကို ကျော်သွားပါတယ်။ - အလယ် ဒါမှမဟုတ် အဆုံးက node ကို ဖယ်ထုတ်ခြင်း:
current.nextမှာ target ရောက်တဲ့အထိ traverse လုပ်ပါ။ ပြီးရင် target node ကို ကျော်ဖို့current.next = current.next.nextလို့ သတ်မှတ်ပါ။ ကျော်ခံရတဲ့ node ကို ဘယ်ကနေမှ ပြန်ရောက်လို့ မရတော့လို့ garbage collection (မသုံးတော့တဲ့ object ရဲ့ memory ကို အလိုအလျောက် ပြန်ယူခြင်း) လုပ်ခံရပါလိမ့်မယ်။
Ben ကို ဖယ်ထုတ်ပြီးနောက် head ဖြစ်တဲ့ Aiko ကို ဖယ်ထုတ်ပုံပါ။ မျဉ်းပြတ်နဲ့ ဆွဲထားတဲ့ node ကို head ကနေ ပြန်ရောက်လို့ မရတော့လို့ list ရဲ့ အစိတ်အပိုင်း မဟုတ်တော့ပါဘူး။
ပုံထဲက “nothing refers to Ben now” က Ben ကို အခု ဘာကမှ မညွှန်းတော့ဘူးလို့ အဓိပ္ပာယ်ရပါတယ်။
ဥပမာ 3: သတ်မှတ်ထားတဲ့ နေရာမှာ ထည့်ခြင်း
// Insert at a given index (0-based)
public void insertAt(int index, String data) {
if (index == 0) {
addToFront(data);
return;
}
Node newNode = new Node(data);
Node current = head;
for (int i = 0; i < index - 1; i++) {
if (current == null) {
return; // index out of bounds
}
current = current.next;
}
if (current == null) {
return; // index out of bounds
}
newNode.next = current.next; // new node points to successor
current.next = newNode; // predecessor points to new node
}
# Insert at a given index (0-based)
def insert_at(self, index, data):
if index == 0:
self.add_to_front(data)
return
new_node = Node(data)
temp = self._head
for i in range(index - 1):
if temp == None:
return # index out of bounds
temp = temp.next
if temp == None:
return # index out of bounds
new_node.next = temp.next # new node points to successor
temp.next = new_node # predecessor points to new node
အလယ်မှာ ထည့်ဖို့ predecessor node (index - 1 နေရာက node) ကို အရင် ရှာပြီး reference တွေကို လမ်းကြောင်း ပြောင်းပေးရပါတယ်:
newNode.nextက predecessor ရဲ့ လက်ရှိ successor ကို ညွှန်းအောင် သတ်မှတ်ပါ- Predecessor ရဲ့
nextက node အသစ်ကို ညွှန်းအောင် သတ်မှတ်ပါ
Element တွေကို နေရာ ရွှေ့ဖို့ မလိုပါဘူး၊ reference နှစ်ခုကို ပြင်ရုံပါပဲ။
Aiko, Carlos, Diana ဆိုတဲ့ list ပေါ်မှာ insertAt(1, "Ben")insert_at(1, "Ben") ကို ခေါ်ပုံပါ။ နောက်ဆုံး ပုံက အစဉ် ဘာကြောင့် အရေးကြီးလဲ ဆိုတာ ပြပါတယ်: predecessor ရဲ့ next ကို အရင် ပြောင်းလိုက်ရင် Carlos ကို ဘာကမှ မညွှန်းတော့ဘဲ ကျန်တဲ့ list တစ်ခုလုံး ပျောက်သွားပါတယ်။
ပုံထဲက English စာတွေရဲ့ အဓိပ္ပာယ်: “Find the node before index 1” က index 1 ရဲ့ ရှေ့က node ကို ရှာပါ၊ “If step 3 runs first” က အဆင့် 3 ကို အရင် run မိရင်၊ “lost: nothing refers to Carlos” က ပျောက်သွားပြီ၊ Carlos ကို ဘာကမှ မညွှန်းတော့ဘူးလို့ အဓိပ္ပာယ်ရပါတယ်။
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. Singly linked list ထဲက node တစ်ခုမှာ ဘာ နှစ်ခု ပါသလဲ။
Q2. Singly linked list ရဲ့ အဆုံးကို ဘယ်လို သိနိုင်သလဲ။
Q3. Singly linked list ရဲ့ ရှေ့ဆုံးမှာ node တစ်ခု ထည့်တဲ့ time complexity (input ကြီးလာရင် ကြာချိန် တိုးပုံ) က ဘာလဲ။
Q4. addToFront method ထဲမှာ newNode.next = head က head = newNode ရဲ့ ရှေ့မှာ ဘာကြောင့် ရှိရမလဲ။
Q5. Singly linked list ရဲ့ အလယ်က node တစ်ခုကို ဖယ်ထုတ်ဖို့ ဘာလုပ်ရမလဲ။
Q6. Node n ခု ပါတဲ့ singly linked list မှာ ပေးထားတဲ့ index က element ကို ယူသုံးတဲ့ worst-case (အဆိုးဆုံး အခြေအနေ) time complexity က ဘာလဲ။
Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)
အောက်က code ကို trace (တစ်ဆင့်ချင်း လိုက်ပြီး မှတ်) လုပ်ပြီး operation (ဒေတာပေါ်မှာ လုပ်တဲ့ လုပ်ဆောင်ချက်) တစ်ခုစီ ပြီးနောက် list ရဲ့ အခြေအနေကို ဖြည့်ပါ။ List ကို code ရဲ့ output ပုံစံအတိုင်း English နဲ့ ရိုက်ထည့်ပါ (ဥပမာ C -> null)။
SinglyLinkedList list = new SinglyLinkedList();
list.addToFront("C");
list.addToFront("B");
list.addToFront("A");
list.addToEnd("D");
list.remove("B");
items = SinglyLinkedList() # "list" is a built-in name in Python
items.add_to_front("C")
items.add_to_front("B")
items.add_to_front("A")
items.add_to_end("D")
items.remove("B")
| ဒီ operation ပြီးနောက် | Head node | List တစ်ခုလုံး (head ကနေ tail အထိ) | size() |
|---|---|---|---|
| addToFront("C") | C -> null | ||
| addToFront("B") | 2 | ||
| addToFront("A") | A -> B -> C -> null | ||
| addToEnd("D") | A | ||
| remove("B") | 3 |
Code Completion (code ကွက်လပ် ဖြည့်ခြင်း)
Linked list ထဲမှာ target value ကို ရှာပေးတဲ့ contains method ကို ဖြည့်ပါ။
List ကို traverse လုပ်ပြီး target ကို ရှာဖို့ ကွက်လပ်တွေကို ဖြည့်ပါ:
public boolean contains(String target) {
Node current = ;
while (current != ) {
if (current.data.(target)) {
return true;
}
current = current.;
}
return false;
}
နောက်ဆုံး node ရဲ့ နောက်မှာ node တစ်ခု ထည့်ပေးတဲ့ addToEnd method ကို ဖြည့်ပါ။
ကွက်လပ်တွေကို ဖြည့်ပါ:
public void addToEnd(String data) {
Node newNode = new (data);
if (head == null) {
head = newNode;
return;
}
Node current = head;
while (current. != null) {
current = current.next;
}
current. = newNode;
}
Spot the Error (အမှား ရှာခြင်း)
ဒီ addToFront method က node အသစ် ထည့်တဲ့အခါ ရှိပြီးသား node အားလုံးကို ပျောက်သွားစေပါတယ်:
မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
ဒီ addToEnd method က NullPointerException ဖြစ်စေပါတယ်:
Line 4 အတွက် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)
ဒီ code က ဘာကို print ထုတ်သလဲ။
SinglyLinkedList nums = new SinglyLinkedList();
nums.addToFront("20");
nums.addToFront("30");
nums.addToFront("10");
nums.printAll();
System.out.println(nums.size());Output ကို အတိအကျ ရိုက်ထည့်ပါ:
ဒီ code က ဘာကို print ထုတ်သလဲ။
SinglyLinkedList colors = new SinglyLinkedList();
colors.addToEnd("Red");
colors.addToEnd("Green");
colors.addToEnd("Blue");
colors.remove("Green");
colors.printAll();
System.out.println(colors.contains("Green"));Output ကို အတိအကျ ရိုက်ထည့်ပါ:
Practice Exercises (လေ့ကျင့်ခန်းများ)
Core (အခြေခံ အဆင့်)
- တည်ဆောက်ပြီး print ထုတ်ပါ။
SinglyLinkedListတစ်ခု ဖန်တီးပြီးaddToEndနဲ့ မြို့နာမည် ငါးခု ထည့်ပါ။ ပြီးရင် list ကို ပြဖို့printAllကို ခေါ်ပါ။ Output ရဲ့ အစဉ်က ထည့်ခဲ့တဲ့ အစဉ်နဲ့ တူမတူ စစ်ကြည့်ပါ။ - Node တွေကို ရေတွက်ပါ။ အပေါ်က
size()method ကို မကြည့်ဘဲ list ကို traverse လုပ်ပြီး node တွေကို ရေတွက်တဲ့ ကိုယ်ပိုင် version ကို ရေးပါ။ Element 0 ခု၊ 1 ခု နဲ့ 5 ခု ပါတဲ့ list တွေနဲ့ စမ်းသပ်ပါ။ - Head ကို ဖယ်ထုတ်ပါ။ Element သုံးခု ပါတဲ့ list တစ်ခု ဖန်တီးပါ။ Head element ကို ဖယ်ထုတ်ပြီး list ကို print ထုတ်ပါ။ ပြီးရင် head ကို နောက်တစ်ခါ ဖယ်ထုတ်ပြီး list ကို print ထုတ်ပါ။ အဆင့်တိုင်းမှာ output ကို စစ်ကြည့်ပါ။
Extension (တိုးချဲ့ အဆင့်)
- Index နဲ့ ယူပါ။ ပေးထားတဲ့ index (0 ကနေ စရေတွက်) က data ကို return (ရလဒ်အဖြစ် ပြန်ပေး) လုပ်တဲ့
public String get(int index)method ကို ရေးပါ။ Head ကနေ စပြီး list ကိုindexကြိမ် traverse လုပ်ပါ။ Index က list ရဲ့ အပိုင်းအခြား ပြင်ပ ရောက်နေရင်nullကို return လုပ်ပါ။ - ရှေ့ဆုံးကို ရွှေ့ပါ။
targetပါတဲ့ ပထမဆုံး node ကို ရှာပြီး အဲဒီ node ကိုယ်တိုင်ကို လက်ရှိ နေရာကနေ ဖြုတ်ကာ head အသစ် အဖြစ် ပြန်ချိတ်ပေးတဲ့public boolean moveToFront(String target)method ကို ရေးပါ (node အသစ် မဖန်တီးပါနဲ့)။targetကို တွေ့ရင်trueကို return လုပ်ပါ (head ဖြစ်ပြီးသား ဆိုရင်လည်းtrueပါပဲ)။ List ထဲမှာ မရှိရင်falseကို return လုပ်ပါ။ အလယ်က node၊ tail၊ head၊ list ထဲမှာ မရှိတဲ့ တန်ဖိုးနဲ့ empty list တို့နဲ့ စမ်းသပ်ပါ။
Challenge (စိန်ခေါ်မှု အဆင့်)
- List ကို ပြောင်းပြန် လှန်ပါ။
nextreference အားလုံးကို လမ်းကြောင်း ပြောင်းပြီး linked list ကို in place (မူလ list ထဲမှာပဲ) ပြောင်းပြန် လှန်ပေးတဲ့public void reverse()method ကို ရေးပါ။prev,currentနဲ့nextNodeဆိုတဲ့ pointer သုံးခုကို သုံးပါ။ ပြောင်းပြန် လှန်ပြီးနောက် tail အဟောင်းက head အသစ် ဖြစ်ရပါမယ်။ - အမှားကို ရှာပြီး ဖော်ပြပါ။ သူငယ်ချင်း တစ်ယောက်က “Insertion က O(1) ဖြစ်လို့ linked list တွေက array တွေထက် အမြဲ ပိုကောင်းတယ်” လို့ ပြောပါတယ်။ ဒီပြောဆိုချက်က ဘာကြောင့် လွဲမှားစေနိုင်လဲ ဆိုတာကို ရှင်းပြတဲ့ စာပိုဒ် တစ်ပိုဒ် ရေးပါ။ Array က ပိုကောင်းတဲ့ ရွေးချယ်မှု ဖြစ်မယ့် အခြေအနေ အနည်းဆုံး နှစ်ခုကို time complexity ကို ကိုးကားပြီး ထည့်ရေးပါ။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: What Are ADTs? (ADT ဆိုတာ ဘာလဲ): interface (class တစ်ခု implement လုပ်ရမယ့် method စာရင်း) နဲ့ implementation (တကယ် အလုပ်လုပ်အောင် ရေးထားတဲ့ code) ကွာခြားချက်ကို နားလည်ခြင်း
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Object References (object reference များ): null၊ aliasing (variable နှစ်ခုက object တစ်ခုတည်းကို ညွှန်းနေခြင်း) နဲ့ reference semantics (object တွေကို reference နဲ့ ကိုင်တွယ်ပုံ)
- ဆက်စပ် ခေါင်းစဉ်: 1D Arrays (တန်းတစ်တန်းတည်းမှာ စီထားတဲ့ ဒေတာအစု): အစဉ်လိုက် ဒေတာအတွက် static အစားထိုး ရွေးချယ်စရာ
- နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: Ordered Linked Lists (တန်ဖိုးအလိုက် အစဉ်တကျ စီထားတဲ့ linked list များ): ထည့်တဲ့အခါ sorted (တန်ဖိုးအလိုက် အစဉ်တကျ စီပြီးသား) အစဉ်ကို ထိန်းထားခြင်း