-
1
faa xumsai Information Technology, The Far Eastern
University
1 Linked List Linked list เป็นโครงสร้าง
(เมื่อเปรียบเทียบกบัอาร์เรย์) ที่ใช้หนว่ยความจ าได้อยา่งดีเยี่ยม
มคีวามยืดหยุน่สงู การใช้เนือ้ที่ในการจดัเก็บข้อมลูไมจ่
าเป็นต้องจองจ านวนท่ีต้องการใช้สงูสดุ
แตจ่ะจดัสรรเนือ้ที่ตามที่ใช้จริง การเข้าหาข้อมลูจะเข้าแบบเป็นล
าดบัขัน้ (Sequential Access) คือจากข้อมลูหนึง่ไปยงัข้อมลูหนึง่ตามล
าดบัก่อนหลงั เชน่ ถ้าต้องการไปยงัข้อมลูที่อยูใ่นล
าดบัท่ีสามจากข้อมลู ณ ต
าแหนง่ปัจจบุนัจะต้องผา่นข้อมลูก่อนหน้าสองตวั (ลองนกึถึงขบวนรถไฟ)
โดยทัว่ไป Linked list จะมีสว่นประกอบหลกัอยูส่องสว่นคอื 1).
สว่นเก็บข้อมลู และ 2). สว่นเช่ือมตอ่
ความคาดหวงัหลงัจากจบบทเรียนนี
้เข้าใจถงึกระบวนการของการจดัการกบัลงิค์ลสิต์ 1ทัง้สามกระบวนการคือ
1). การน าข้อมลูเข้า 2). การลบข้อมลู และ 3). การค้นหาข้อมลู
โดยเฉพาะเมือ่ท ากบัโครงสร้างตอ่ไปนี ้
1. ลสิต์ทางเดียว (Singly linked list) 2. ลสิต์สองทาง (Doubly
linked list) 3. ลสิต์วนกลบั (Circular linked list)
1.1 ลสิต์ทางเดียว (Singly linked list) Singly linked list
เป็นโครงสร้างที่ใช้ node มาเช่ือมตอ่กนัให้เป็นลสิต์ โดยในแตล่ะ node
จะมีสว่นท่ีเป็นข้อมลู (data) และสว่นท่ีเป็นตวัเช่ือมไปยงั node
ถดัไป (link) รูปท่ี 1.1 แสดงลสิต์ทางเดียวทีม่ีข้อมลูเป็น
integer
รูปที่ 1.1 Singly linked list
การออกแบบ node ส าหรับหนงัสอืเลม่นีจ้ะใช้สว่น2ที่ช่ือ data
เป็นท่ีเก็บข้อมลูและสว่นท่ีช่ือ next เป็นตวัเช่ือม3 ส าหรับ Singly
linked list รูปท่ี 1.2 แสดงสว่นประกอบของ node และ node
สดุท้ายของลสิต์
รูปที่ 1.2 โครงสร้างของ node [data และ link] และวิธีแสดง node
สดุท้ายของ Linked list ใน diagram
1
จะใช้สลบักนัไปมาระหวา่งลิงค์ลสิต์และลสิต์แตจ่ะหมายถึงสิ่งเดียวกนัคือ
ลงิค์ลิสต์
2 หนงัสือหลาย ๆ เลม่เรียกสว่นตา่ง ๆ ใน node วา่ฟิลด์ (field)
หรือสมาชิก (member)
3 ตวัเชื่อม ตวัชี ้หรือ link คือการอ้าง (reference) ถึง node
อ่ืน (ถ้าม)ี ในลิสต์
free
know
ledg
e so
ciet
y
-
2
faa xumsai Information Technology, The Far Eastern
University
เราจะใช้ node พิเศษสอง node ส าหรับเป็นตวัชีไ้ปยงั node
ที่อยูด้่านหน้าและ node ที่อยูท้่ายสดุในลสิต์ คือ head และ tail
ซึง่การก าหนดในลกัษณะนีจ้ะท
าให้การเข้าหาข้อมลูทัง้ด้านหน้าและด้านหลงั (node
แรกสดุของทัง้สองทางดงัที่แสดงในรูปท่ี 1.1) ท าได้ในเวลาทีเ่ทา่กนั ส
าหรับ node ที่ tail ชีอ้ยูแ่ละเป็น node สดุท้ายของลสิต์เราจะก
าหนดให้ชีไ้ป
ยงั null node (หรือ nil) ซึง่เราใช้สญัลกัษณ์ Ø แทน
และทกุครัง้เมื่อมกีารสร้างลสิต์เราจะก าหนดให้ head และ tail ชี
้ไปท่ี null node เสมอเพื่อเป็นการก าหนดถึงลสิต์ที่ยงัไมม่ีข้อมลู
(empty list)
1.1.1 การน าข้อมลูเข้า (Insertion) ในการน าข้อมลูเข้าสู ่linked
list นัน้เรามกัจะน าเข้าทางด้านหลงั (node ที่ tail ชีอ้ยู)่ แตก่ารน
าเข้าทางด้านหน้าหรือ ณ ต าแหนง่อื่น ๆ ใน linked list ก็สามารถท
าได้เช่นกนั ทัง้นีก้ารน าเข้าข้อมลูเราจะต้องค
านงึถงึกรณีหลกัสองกรณีคือ
head ชีไ้ปท่ี null ซึง่หมายถงึ linked list ที่ไมม่ีข้อมลูอยูเ่ลย
หรือ linked list มีข้อมลูอยูซ่ึง่การน าเข้าก็คือการเช่ือม node
ใหมเ่ข้าสูล่สิต์พร้อมกบัปรับ head หรือ tail ให้ชีไ้ปยงั
node ใหมท่ี่พึง่น าเข้านี ้
การน าข้อมลูเข้าทางด้านหลงัของ linked list เร่ิมด้วยการสร้าง
node ใหมส่ าหรับข้อมลูที่ต้องน
าเข้าพร้อมกบัตรวจสอบวา่ลสิต์มีข้อมลูหรือไม
่ถ้าลสิต์ไมม่ีข้อมลูเลยก็ย้าย head และ tail ไปท่ี node ใหมน่ี
้แตถ้่าลสิต์มข้ีอมลูอยู่ให้ย้ายตวัเช่ือมจาก node tail ไปยงั node
ใหมส่ร้างขึน้พร้อมกบัย้าย tail มาชีท้ี่ node ใหมน่ี ้
รูปที่ 1.3 การน าข้อมลูเข้าเม่ือลิสต์ไมมี่ข้อมลู
รูปที่ 1.4 การน าข้อมลูเข้าทางด้านหลงัของลิสต์ 01: Algorithm
insertAtTail(item) 02: Begin 03: newNode new Node(value) 04: If
head = null
free
know
ledg
e so
ciet
y
-
3
faa xumsai Information Technology, The Far Eastern
University
05: tail head newNode 06: Else 07: tail.next newNode 08: tail
newNode 09: End If 10: End insertAtTail
การน าข้อมลูเข้าด้านหน้าของ Linked list นัน้ก็คล้ายกบัการน
าเข้าทางด้านหลงั ถ้าลสิต์ไมม่ข้ีอมลูก็ท
าในลกัษณะเดียวกนัแตถ้่ามีเราก็ย้ายตวัเช่ือมจาก node
ใหมท่ี่สร้างขึน้ไปท่ี head หลงัจากนัน้ก็ย้าย head ไปที่ node ใหมน่ี
้
รูปที่ 1.4 การน าข้อมลูเข้าทางด้านหน้าของลิสต์ 01: Algorithm
insertAtHead(item) 02: Begin 03: newNode new Node(value) 04: If
head = null 05: tail head newNode 06: Else 07: newNode.next head
08: head newNode 09: End If 10: End insertAtHead
1.1.2 การลบข้อมลู (Deletion) การลบข้อมลูออกจาก Linked list
ทางด้านหน้านัน้ท าได้ง่ายกวา่ทางด้านหลงั เราเพียงแตย้่าย head
ให้ชีไ้ปยงั node ถดัไปก็จบ
แตก่ารลบออกจากทางด้านหลงันัน้เราต้องค้นหา node ที่อยูก่่อน tail
ให้เจอเพื่อท่ีจะย้ายตวัเช่ือมจาก node นีไ้ปยงั null
ซึง่ก็หมายถึงการเดนิเข้าหาทกุ node ที่มีอยูใ่นลสิต์ (ใช้เวลามากถ้าจ
านวนของ node มีมาก) รูปท่ี 1.5 แสดงการลบ node
ออกทางด้านหน้าของลสิต์
รูปที่ 1.5 การลบจากทางด้านหน้าของลิสต์ 01: Algorithm
removeAtHead() 02: Begin 03: //case 1: empty list 04: If head =
null 05: Return false 06: End If
free
know
ledg
e so
ciet
y
-
4
faa xumsai Information Technology, The Far Eastern
University
07: //case 2: list has at least one node 08: head head.next 09:
Return true 10: End removeAtHead
ส าหรับการลบ node
ออกทางด้านหลงัของลสิต์เราต้องเดินเข้าหาลสิต์ทีละ node เพื่อหา node
ก่อนหน้า tail ให้เจอเพื่อท่ีจะได้ก าหนดให้ tail ชีไ้ปท่ี node นี
้(ดรููปท่ี 1.6)
รูปที่ 1.6 การลบจากทางด้านหลงัของลิสต์ 01: Algorithm
removeAtTail() 02: Begin 03: //case 1: empty list 04: If head =
null 05: Return false 06: End If 07: //case 2: list has at least
one node 08: beforeTail head 09: While beforeTail != tail do 10:
beforeTail beforeTail.next 11: End while 12: beforeTail.next null
13: tail beforeTail 14: Return true 15: End removeAtTail
ยงัมกีระบวนการอื่น ๆ ที่เราอาจต้องสร้างขึน้เพื่อรองรับการท
างานท่ีจ าเป็น เช่น การน าข้อมลูเข้าในท่ีที่ก าหนดให้
การลบข้อมลูออกจากต าแหนง่ทีก่ าหนด ซึง่กระบวนการตา่ง ๆ เหลา่นีก็้ท
าได้ไมย่าก เราจะแสดงกระบวนการตา่ง ๆ นีใ้ห้ดใูนล าดบัถดัไป
1.1.3 การน าข้อมลูเข้าหรือดงึออกหลงั node ที่ก าหนดให้
กระบวนการทัง้สองนีต้้องหา node ที่ก าหนดให้ให้เจอ
ซึง่เมื่อหาเจอแล้วขัน้ตอนตอ่ไปก็งา่ยขึน้
เราเพียงแตย้่ายตวัเช่ือมให้อยูใ่นต าแหนง่ทีเ่หมาะสม
(ถ้าไมเ่จอก็ไมต้่องลบ) รูปท่ี 1.7 แสดงการลบ node ที่อยูถ่ดัไปจาก
node ที่ก าหนดให้ และรูปที่ 1.8 แสดงการน า node เข้าหลงั node ที่ก
าหนดให้
free
know
ledg
e so
ciet
y
-
5
faa xumsai Information Technology, The Far Eastern
University
รูปที่ 1.7 การลบจากทางด้านหลงัของ node ที่ก าหนด 01: Algorithm
removeAfter(key) 02: Begin 03: cur search(key) 04: If cur = null
05: Return false 06: End If 07: forward cur.next.next 08: cur.next
forward 09: Return true 10: End removeAfter
อลักอริทมึส าหรับการค้นหาก็ออกแบบง่าย ๆ ด้วยการเดินเข้าหา node
ทกุตวัที่อยูใ่นลสิต์พร้อมกบัท าการเปรียบข้อมลูของ node
กบัข้อมลูที่ต้องการค้นหา (key)
ถ้าข้อมลูที่ต้องการค้นหามีอยูใ่นลสิต์เราก็สง่ node ที่มีข้อมลูกลบั
แตถ้่าข้อมลูไมม่ีอยูใ่นลสิต์คา่ทีเ่ราสง่กลบัคือ null
ผู้อา่นคงจะสงัเกตเหน็วา่การค้นหาข้อมลูที่ไมม่ีอยูใ่นลสิต์นัน้เราต้องใช้เวลาค้นหาไปจนหมด
node ที่มีอยูใ่นลสิต์ ซึง่เป็นการใช้เวลามากถ้าจ านวน node มีมาก 01:
Algorithm search(key) 02: Begin 03: cur head 04: While cur != null
&& cur.data != key do 05: cur cur.next 06: End While 07:
Return cur 08: End search
รูปที่ 1.8 การน า node เข้าทางด้านหลงัของ node ที่ก าหนด
free
know
ledg
e so
ciet
y
-
6
faa xumsai Information Technology, The Far Eastern
University
01: Algorithm insertAfter(key) 02: Begin 03: cur search(key) 04:
If cur = null 05: Error: ‘Given doesn’t exist’ 06: Else 07: newNode
new Node(value) 08: newNode.setNext(cur.getNext()) 09:
cur.setNext(newNode) 10: End If 11: End insertAfter
1.1.4 การน าข้อมลูเข้าหรือออกก่อนหน้า node ที่ก าหนดให้ การน
าเข้าหรือลบออกจาก node ที่ก าหนดให้ก็คล้ายกบัการกระท าหลงั node
ที่ก าหนดให้ ตา่งกนัตรงที่เราต้องจ า node ที่อยูก่่อนหน้า node
ที่ได้ถกูก าหนดไว้เพื่อการโยกย้ายตวัเช่ือม รูปท่ี 1.9 แสดงการน า
node เข้าสว่นรูปท่ี 1.10 แสดงการลบ node ออก
รูปที่ 1.9 การน า node เข้าทางด้านหน้าของ node ที่ก าหนด
รูปท่ี 1.9 แสดงการน าเข้าด้านหน้าของ node ที่ก
าหนดให้เฉพาะกรณีทัว่ไป แตก่รณีที่ต้องน าเข้าก่อน node ที่ head ชี
้อยูต้่องตรวจสอบเพิ่มเติมวา่ cur ชีอ้ยูท่ี่เดียวกนักบั head
หรือไมเ่พื่อให้การเช่ือมตอ่จาก head ไปยงั node ใหมเ่ป็นไปได้
(บรรทดัที่ 12 – 14 ในอลักอริทมึ) 01: Algorithm insertBefore(key,
item) 02: Begin 03: before cur head 04: While cur != null
&& cur.data != key do 05: before cur 06: cur cur.next 07:
End while 08: If cur = null 09: Error: Key doesn’t exist 10: Else
11: temp new Node(item) 12: If cur = head 13: head = temp 14: Else
15: before.next temp 16: End If 17: End If 18: End insertBefore
free
kno
wle
dge
soci
ety
-
7
faa xumsai Information Technology, The Far Eastern
University
รูปที่ 1.10 การลบ node ที่อยูก่่อนหน้าของ node ที่ก าหนดให้
รูปท่ี 1.10 แสดงการลบ node กอ่นหน้า node ที่มีข้อมลูที่ก
าหนดให้ในกรณีที่ node นีไ้มไ่ด้อยูถ่ดัจาก head ทนัที ขัน้ตอนท่ีเราท
าคือเดินเข้าหาลสิต์ด้วยตวัชีส้องตวั ตวัหนึง่อยูก่่อนหน้า node ที่มี
key อยูอ่ีก node หนึง่อยูก่่อนหน้าสอง node (cur และ before) เมื่อหา
node ทัง้สองเจอแล้วเราก็ย้ายตวัเช่ือมจาก before ไปยงั node ที่ก
าหนดให้ ส าหรับกรณีที่ key อยูถ่ดัจาก head ทนัทีสิง่ที่เราต้องท
าก็คือย้ายตวัเช่ือมของ head ไปยงั node ที่อยูด้่านหลงัของ node
ก่อนหน้า key 01: Algorithm removeBefore(key) 02: Begin 03: //case
1: empty list 04: If head = null 05: Return false 06: End If 07:
before cur head 08: While cur.next != null && cur.next.data
!= key do 09: before cur 10: cur cur.next 11: End While 12: //case
2: key is not in the list 13: If cur.next = null 14: Return false
15: End If 16: //case 3: key is after head node 17: If cur = head
18: head head.next 19: Return true 20: End If 21: //case 4: other
cases 22: before.next cur.next 23: Return true 24: End
removeBefore
1.1.5 Big O ของ Singly linked list
จากอลักอริทมึที่เราได้กลา่วมาทัง้หมด ผู้อา่นจะเห็นวา่ในการน
าข้อมลูเข้าสูล่สิต์นัน้มีอยูส่องกรณีหลกั คือ 1). เข้าที่ head หรือ
tail ชีอ้ยู ่และ 2). เข้า ณ ต าแหนง่อื่น การน
าเข้าทางด้านหน้าหรือหลงันัน้ท
าได้ทนัทีเพราะฉะนัน้เราจงึใช้เวลาไปเทา่กบั Ο(1) สว่นการน
าเข้าในท่ีอื่น ๆ ต้องมีการคนัหาต
าแหนง่ที่เหมาะสมดงันัน้เราจงึใช้เวลาไปทัง้สิน้ Ο(n) เช่นเดียวกนั
การค้นหาและการลบข้อมลูก็ต้องมีการเดินเข้า node
ที่มีอยูใ่นลสิต์ดงันัน้จงึใช้เวลาไปเทา่กบั Ο(n)
free
know
ledg
e so
ciet
y
-
8
faa xumsai Information Technology, The Far Eastern
University
1.2 ลสิต์สองทาง (Doubly linked list)
ลสิต์สองทางเป็นลสิต์ที่ปรับปรุงมาจากลสิต์ทางเดียวเพื่อตอบสนองการเดินเข้าหาลสิต์ในรูปแบบที่เป็นไปได้ทัง้สองทาง
คือทางด้านหน้าและด้านหลงั การท าในลกัษณะนีท้ าให้กระบวนการตา่ง ๆ
ที่เราต้องท ากบัลสิต์ท าได้ไวขึน้ เช่นการลบ node ก่อนหน้า tail
ที่เราท าในลสิต์ทางเดียว ใน Doubly linked list
เราไมต้่องเดินเข้าหาลสิต์จากทางด้านหน้าอีกตอ่ไปเราสามารถลบ node
ดงักลา่วออกทางด้านหลงัได้ทนัที แตเ่ราต้องออกแบบให้ node
ของเรามีตวัเช่ือมอีกหนึง่ตวัส าหรับเช่ือม node ก่อนหน้า รูปท่ี 1.11
แสดง Doubly linked list
รูปที่ 1.11 Doubly linked list
1.2.1 การน าข้อมลูเข้า (Insertion) การน าข้อมลูเข้าสู ่Doubly
linked list ทัง้สองทางท าในลกัษณะเดียวกนัคือ สร้าง node ใหมส่
าหรับข้อมลูที่ต้องการน าเข้า ย้ายตวัเช่ือมตา่ง ๆ ไปยงัต
าแหนง่ทีเ่หมาะสม การน
าเข้าในกรณีที่ไมม่ีข้อมลูอยูใ่นลสิต์นัน้สิง่ที่เราต้องท าคือย้าย
tail มาชีท้ี่ node
ใหมแ่ตถ้่ามีข้อมลูอยูเ่ราต้องย้ายตวัเช่ือมกลบัของ head มาที่ node
ใหมน่ี ้ขัน้ตอนที่เหลอืของทัง้สองกรณีคือการเช่ือมตวัชีข้อง node
ใหมไ่ปท่ี head พร้อมกบัการย้าย head ไปท่ี node ใหม ่รูปท่ี 1.12
แสดงการน าเข้าในกรณีที่ลสิต์มีข้อมลูอยู ่
รูปที่ 1.12 การน าข้อมลูเข้าด้านหน้าของ Doubly linked list 01:
Algorithm insertAtHead(value) 02: Begin 03: newNode new Node(value)
04: If head = null 05: tail newNode 06: Else 07: head.previous
newNode 08: End If 09: newNode.next head 10: head newNode 11: End
insertAfter
free
know
ledg
e so
ciet
y
-
9
faa xumsai Information Technology, The Far Eastern
University
ส าหรับการน าข้อมลูเข้าทางด้านหลงันัน้ เราก็ท
าคล้ายกบัทางด้านหน้าในกรณีที่ลสิต์ไมม่ีข้อมลูอยูเ่ราก็ก าหนดให้
head ชี ้ไปท่ี node ใหม ่แตถ้่ามีข้อมลูเราต้องย้ายตวัเช่ือมไปของ
tail ไปท่ี node ใหมพ่ร้อมกบัย้ายตวัเช่ือมกลบัของ node ใหม่ไปท่ี
tail และขัน้ตอนสดุท้ายของทัง้สองกรณีคือการย้าย tail ไปชีท้ี่ node
ใหม ่(ดรููปท่ี 1.13)
รูปที่ 1.13 การน าข้อมลูเข้าด้านหลงัของ Doubly linked list 01:
Algorithm insertAtTail(value) 02: Begin 03: newNode new Node(value)
04: If head = null 05: head newNode 06: Else 07: tail.next newNode
08: newNode.previous tail 09: End If 10: tail newNode 11: End
insertAtTail
1.2.2 การลบข้อมลู (Deletion)
การลบข้อมลูออกจากลสิต์ทางด้านหน้าเราต้องค านงึถงึ 1).
กรณีที่ลสิต์ไมม่ีข้อมลู 2). กรณีที่ลสิต์มีข้อมลูเพียงหนึง่ตวั และ
3). กรณีที่ลสิต์มีข้อมลูมากกวา่หนึง่ตวั กรณีที่ 1). และ 2).
นัน้ง่ายมากเราเพียงแคก่ าหนดให้ head และ/หรือ tail มีคา่เป็น null
สว่นกรณีที่ 3). เราย้ายตวัเช่ือมกลบัของ node ที่อยูถ่ดัจาก head
(ถ้ามี) ไปท่ี null และย้าย head ไปยงั node นีห้ลงัจากนัน้ ดรููปท่ี
1.14
รูปที่ 1.14 การลบข้อมลูออกทางด้านหน้าของ Doubly linked list 01:
Algorithm removeAtHead() 02: Begin 03: //case 1: empty list 04: If
head = null
free
know
ledg
e so
ciet
y
-
10
faa xumsai Information Technology, The Far Eastern
University
05: Return null 06: End If 07: //case 2: list with one node 08:
If head.next = null 09: head tail null 10: //case 3: list with more
than one node 11: Else 12: head.next.previous null 13: head
head.next 14: End If 15: End removeAtHead
ส
าหรับการลบข้อมลูจากด้านหลงัของลสิต์ก็คล้ายกบัทางด้านหน้าตา่งกนัเพียงแคก่ารย้ายตวัเช่ือมของ
tail แทนการย้ายตวัเช่ือมของ head ดรููปท่ี 1.15
รูปที่ 1.15 การลบข้อมลูออกทางด้านหลงัของ Doubly linked list 01:
Algorithm removeAtTail() 02: Begin 03: //case 1: empty list 04: If
head = null 05: Return null 06: End If 07: //case 2: list with one
node 08: If head.next = null 09: head tail null 10: //case 3: list
with more than one node 11: Else 12: tail.previous.next null 13:
tail tail.previous 14: End If 15: End removeAtTail
1.2.3 การน าข้อมลูเข้าแบบจดัเรียง (In-order Insertion) การน
าข้อมลูเข้าแบบที่ต้องค านงึถึงต าแหนง่ของข้อมลูก่อนหลงั
เช่นจากน้อยไปหามากจ าเป็นต้องหาต
าแหนง่ที่เหมาะสมในลสิต์ให้กบัข้อมลู ซึง่โดยทัว่ไปก็มีอยูส่ี่กรณีคือ
1). ลสิต์ไมม่ีข้อมลู 2). น าเข้าด้านหน้า 3). น าเข้าด้านหลงั และ
4). น าเข้าระหวา่ง node ซึง่ทกุกรณีดงักลา่ว (ยกเว้นกรณีที่ 1)
เราต้องเดินเข้าหาลสิต์เพื่อเปรียบเทียบข้อมลูในการหาต
าแหนง่ทีถ่กูต้อง 01: Algorithm insertInorder(value) 02: Begin 03:
//case 1: empty list 04: If head = null 05: insertAtHead(value) 06:
Return 07: End If 08: //search for proper position 09: cur head 10:
While cur != null do 11: If value > cur.data 12: cur
cur.next
free
know
ledg
e so
ciet
y
-
11
faa xumsai Information Technology, The Far Eastern
University
13: Else 14: Break 15: End While 16: newNode = new Node(value)
17: //case 2: insert before head node 18: If cur = head 19: head
newNode 20: head.next cur 21: cur.previous newNode 22: //case 3:
insert at tail 23: Else If cur = null 24: tail.next newNode 25:
newNode.previous tail 26: tail newNode 27: //case 4: insert between
nodes 28: Else 29: newNode.next cur 30: cur.previous.next newNode
31: newNode.previous cur.previous 32: cur.previous newNode 33: End
If 34: End insertInorder
1.3 ลสิต์แบบวนกลบั (Circular linked list)
ลสิต์แบบวนกลบัหมายถึงลสิต์ทีเ่ราก าหนดให้ตวัเช่ือมไปของ node
สดุท้ายชีก้ลบัไปท่ี node แรกของลสิต์ซึง่ข้อดีของการท
าแบบนีค้ือการเข้าหาnode ด้านหน้าและด้านหลงัใช้เวลาเทา่กนั ดรููปท่ี
1.16
รูปที่ 1.16 Circular linked list
Singly linked list โดยทัว่ไปจะมี node พิเศษทีเ่รียกวา่ head
ชีอ้ยูท่ี่ node แรกสดุของลสิต์ แตส่ าหรับลสิต์แบบวนกลบัเราจะใช้
tail4 แทน head ทัง้นีก็้เพราะวา่การมี head
อยูก็่ไมช่่วยให้การเข้าหาลสิต์ดีขึน้ ซึง่ตรงกนัข้ามกบัการมี tail
เราสามารถเข้าหาทัง้ head และ tail ได้ในเวลาที่เทา่กนั
1.3.1 การน าข้อมลูเข้า (Insertion) เนื่องจากวา่เราใช้ตวัชี ้tail
เป็นตวัก าหนดการเข้าหาลสิต์ ดงันัน้การน าข้อมลูเข้า
(ทัง้ด้านหน้าและด้านหลงั) จึงต้องท าผา่นทาง tail เช่นเดียวกบัการน
าเข้าโดยทัว่ไป (น าเข้าทางด้านหน้าของลสิต์) เราต้องค
านงึถึงกรณีที่ลสิต์มีและไมม่ีข้อมลูอยู
่ในกรณีที่ลสิต์ไมม่ีข้อมลูเราก็เพียงแคก่ าหนดให้ tail ชีไ้ปท่ี node
ใหมท่ี่เราสร้างขึน้และตวัชีข้อง tail ชีไ้ปท่ีตวัเอง (บรรทดัที่ 07
ในอลักอริทมึ) ส าหรับกรณีที่ลสิต์มีข้อมลูอยูเ่ราต้องก
าหนดให้ตวัชีข้อง node ใหมชี่ไ้ปยงั node ที่ tail ชี
้(ซึง่อาจเป็นตวัมนัเองถ้าลสิต์มีเพยีงข้อมลูเดียว) หลงัจากนัน้ก็ก
าหนดให้ตวัชีข้อง tail ชีไ้ปท่ี node ใหมน่ี ้ 01: Algorithm
insert(value) 02: Begin 03: newNode new Node(value) 04: //case 1:
empty list 05: If tail = null
4 แนะน าโดย Duane A. Bailey
free
know
ledg
e so
ciet
y
-
12
faa xumsai Information Technology, The Far Eastern
University
06: tail newNode 07: tail.next tail 08: Else 09: //case 2: list
has at least one node 10: newNode.next tail.next 11: tail.next
newNode 12: End If 13: End insert
รูปที่ 1.17 การน าข้อมลูเข้าเม่ือลิสต์ไมมี่ข้อมลู (ซ้าย)
และเม่ือลิสต์มีข้อมลูอยูอ่ยา่งน้อยหนึ่งตวั (ขวา)
เรารู้วา่ลสิต์แบบวนกลบันีจ้ะต้องก าหนดให้ tail ชีไ้ปท่ี node
ที่อยูด้่านหลงัสดุเสมอดงันัน้การน
าข้อมลูเข้าทางด้านหลงัก็เป็นเพียงแคก่ารน
าข้อมลูเข้าตามปกติทางด้านหน้าแล้วก็ย้ายตวั tail เองไปชีท้ี่ node
ใหมท่ี่น าเข้านี ้ดรููปท่ี 1.18 01: Algorithm insertAtTail(value)
02: Begin 03: insert(value) 04: tail tail.next 05: End
insertAtTail
รูปที่ 1.18 การน าข้อมลูเข้าทางด้านหลงัของลิสต์
การลบข้อมลูออกจากลสิต์ (ไมว่า่จะเป็นด้านหน้าหรือด้านหลงั)
สิง่ที่เราต้องท าก็คือการย้ายตวัชีไ้ปอยูใ่นต าแหนง่ที่เหมาะสม
ในการลบด้านหน้านัน้สิง่ที่เราต้องค านงึหลกั ๆ คือ 1).
กรณีที่ลสิต์มีเพียงแคห่นึง่ node และ 2). กรณีที่มีมากกวา่หนึง่ node
ถ้าลสิต์มีแค ่node เดียวเราก็ก าหนดให้ tail มีคา่เป็น null
ก็จบแตถ้่ามีมากกวา่หนึง่ node เราต้องก าหนดให้ตวัชีข้อง tail
ชีไ้ปท่ี node ที่อยูห่า่งออกไปจาก tail สอง node (เร่ิมนบัจากตวั
tail เอง)
free
know
ledg
e so
ciet
y
-
13
faa xumsai Information Technology, The Far Eastern
University
01: Algorithm remove() 02: Begin 03: //case 1: empty list 04: If
tail = null 05: Return null 06: //case 2: list with one node 07:
Else if tail = tail.next 08: tail null 09: //other case 10: Else
11: tail.next tail.next.next 12: End If 13: End remove
รูปที่ 1.19 การลบข้อมลูออกทางด้านหน้าของลิสต์
การลบข้อมลูออกจากทางด้านหลงัของลสิต์ดเูผิน ๆ
แล้วก็นา่จะงา่ยเพราะเรามี tail ชีท้ี่ node
สดุท้ายแตใ่นความเป็นจริงแล้วเราต้องหา node ก่อนหน้า node ที่ tail
ชีอ้ยูใ่ห้เจอเพื่อท่ีเราจะได้ย้ายตวัชีใ้ห้อยูใ่นต าแหนง่ที่เหมาะสม
อลักอริทมึส าหรับการน าเข้าแบบนีเ้ร่ิมที่การก าหนดให้มีตวัชี ้(cur
ในอลักอริทมึ) ชีไ้ปยงั node สดุท้าย ท
าการเดินเข้าหาลสิต์จนกวา่จะมาถึง node ก่อนหน้า tail (next
ของตวัชีน้ีชี้ไ้ปยงั tail) ท าการย้ายตวัเช่ือมของ node
นีใ้ห้ไปชีท้ี่ next ของ tail ชีอ้ยู ่หลงัจากนัน้ก็ย้าย tail ไปท่ี
node ก่อนหน้า tail ส าหรับกรณีที่ลสิต์มี node เพียง node
เดียวการเดินเข้าหาลสิต์จะไม่เกิดขึน้ (cur.next = tail) เราก็ก
าหนดให้ tail มีคา่เป็น null
รูปที่ 1.20 การลบข้อมลูออกทางด้านหลงัของลิสต์ 01: Algorithm
removeAtTail() 02: Begin 03: //case 1: empty list
free
know
ledg
e so
ciet
y
-
14
faa xumsai Information Technology, The Far Eastern
University
04: If tail = null 05: Return null 06: End If 07: //search for
the node before tail 08: cur tail 09: While cur.next != tail do 10:
cur cur.next 11: End While 12: //case 2: only one node 13: If cur =
tail 14: tail null 15: //case 3: more than one node 16: Else 17:
cur.next tail.next 18: tail cur 19: End If 20: End removeAtTail
free
know
ledg
e so
ciet
y