The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.
Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by kittisaksoulz, 2022-03-27 12:57:27

ebook โครงสร้างข้อมูลและขั้นตอนวิธี

ilovepdf_merged (1)

บทที่ 4
โครงสร้างข้อมลู แบบลงิ คล์ สิ ต์

ตวั แปรที่ประกาศใช้ในโปรแกรมที่เป็นอาร์เรย์ เป็นตัวแปรชนิดที่ใช้เน้ือที่ในหน่วยความจำแบบ
สถติ (Static Memory Allocation) หมายความว่า ในช่วงของการประมวลผลโปรแกรม คอมพิวเตอร์ได้
มกี ารจัดสรรเน้ือที่ในหน่วยความจำใหก้ ับตัวแปรแต่ละตัวล่วงหนา้ ในขนาดท่คี งที่ตามทไ่ี ด้ประกาศตัวแปร
ไว้ จึงมีข้อเสียเกิดข้ึนเนื่องจากไม่สามารถเพิ่มหรือลดขนาดของหน่วยความจำให้สัมพันธ์หรือสอดคล้อง
กับลักษณะของงาน เช่น ในช่วงของการประมวลผลหากมีข้อมูลให้เคร่ืองทำการอ่านเข้าไปเก็บไว้ใน
อาร์เรย์จำนวนน้อยกว่าการประกาศการใช้เน้ือที่มีผลทำให้ส่วนพ้ืนท่ีที่เหลืออยู่ในหน่วยความจำของ
อาร์เรย์ไม่ถูกใช้งาน แต่ไม่สามารถนำไปจัดสรรเพ่ือการอ่ืนได้ จึงเป็นข้อเสียเพราะใช้พ้ืนท่ีใน
หน่วยความจำอย่างไม่มีประสิทธภิ าพ สิ้นเปลืองโดยไมจ่ ำเป็น และในทางกลบั กนั หากขอ้ มลู ตอ้ งการเก็บ
ไวใ้ นอาร์เรย์มีปริมาณมาก ซง่ึ อาร์เรย์ท่ีประกาศคา่ ไวเ้ ดมิ ไม่สามารถรองรบั ค่าไดห้ มด หากจะขยายขนาด
ของอาร์เรย์ในช่วงการประมวลผลก็ทำไม่ได้จำเป็นต้องระงับการประมวลผลไว้ก่อน แล้วจึงขยายขนาด
อารเ์ รย์ตรงส่วนประกาศเพิ่มเพอื่ ใหม้ ขี นาดใหญ่ขนึ้ ซึ่งจะสร้างความไมส่ ะดวกอย่างยิ่ง

จากปัญหาการใช้พื้นท่ีในหน่วยความจำดังกล่าว จึงมีวิธีการสร้างตัวแปรประเภทที่มีลักษณะ
การจัดสรรหน่วยความจำแบบพลวัต (Dynamic Memory Allocation) หมายความว่า การจัดสรร
ห น่ ว ย ค ว าม จ ำที่ ไม่ จ ำเป็ น ต้ อ งจั ด ส ร ร เน้ื อ ที่ ใน ห น่ ว ย ค ว ามจ ำให้ กั บ ตั วแป ร ท่ี ต้ องก ารใช้ ก่ อ น การ
ประมวลผล จนกว่าจะถึงช่วงของการประมวลผลโปรแกรม ตัวแปรแบบพลวัตสามารถสร้างข้ึนมาได้ทุก
คร้ังเม่ือต้องการใช้ และสามารถทำลายเพื่อคืนเน้ือที่ในหน่วยความจำให้กับระบบเมื่อไม่ต้องการใช้แล้ว
ซึ่งจะสร้างความสะดวกเพราะสามารถเพ่ิมหรือลดขนาดได้ตามความเหมาะสมของงานและสามารถใช้
หน่วยความจำเท่าท่ีใช้งานจริงๆ จึงทำให้การจัดสรรหน่วยความจำแบบพลวัต สามารถใช้งานภายใน
หนว่ ยความจำได้อย่างเต็มประสทิ ธภิ าพ ตัวแปรแบบพลวตั รทกี่ ล่าวถึงนีไ้ ดแ้ ก่ ลงิ ค์ลสิ ต์ (Linked list)

4.1 แนวคิดพนื้ ฐานเก่ียวกบั ลิงค์ลิสต์
ลิงค์ลิสต์เป็นโครงสร้างข้อมูลแบบเชิงเส้นท่ีมีลักษณะการเก็บของข้อมูลด้วยโหนด (Node)

ต่อเน่ืองกัน โดยแต่ละโหนดจะถูกระบุตำแหน่งบนหน่วยความจำ (Address) เพ่ือใช้อ้างอิงหรือการ
เข้าถึงได้ โหนดจะประกอบด้วย 2 สว่ น คือส่วนข้อมลู ของลงิ ค์ลสิ ต์ (Data) เป็นส่วนที่ใชจ้ ดั เกบ็ ขอ้ มลู จะ
มีการเก็บสารสนเทศท่ีสามารถนำไปใช้ประโยชน์ เพื่อนำไปใช้ในการประมวลผลตามที่ต้องการต่อไป
และส่วนลิงค์ (Link) ท่ีจัดเก็บพอยน์เตอร์เป็นตัวแปรเก็บค่าอ้างอิงไปยังท่ีอยู่ของโหนดถัดไป โดยลงิ ค์จะ
ใชเ้ พื่อเชอ่ื มโยงไปยังขอ้ มูล จะเรมิ่ จากพอยตเ์ ตอร์ Head (pHead) ท่ีชไี้ ปยงั ตำแหนง่ โหนดแรกของลิสต์
จากนัน้ ลงิ คข์ องแต่ละโหนดก็จะเช่อื มโยงไปยังโหนดถัดไปเร่ือยๆ โดยที่โหนดสุดท้ายจะเก็บค่าอ้างองิ

48

เป็น Null หรือ Nil แสดงวา่ เป็นจุดสนิ้ สุดของลิงค์ลิสต์ดังภาพประกอบท่ี 4.1

pHead Data Link Data Link
…R … U Null

Address 23 12 35

ภาพประกอบที่ 4.1 ตวั อย่างลิงค์ลสิ ต์แบบพื้นฐาน

จากภาพประกอบที่ 4.1 ตัวอยา่ งลิงคล์ สิ ตแ์ บบพน้ื ฐานประกอบด้วยพอยเตอร์ pHead
เป็นพอยเตอร์ช้ที ี่โหนดแรกซ่งึ พอยเตอร์นเ้ี ก็บในตำแหน่งท่ี 23 ในหนว่ ยควาและทำการชี้ทโ่ี หนดที่เก็บ
ขอ้ มลู R ซ่ึงถูกเกบ็ ข้อมลู ในตำแหนง่ ที่ 12 ในหน่วยความจำ ซ่ึงลิงคล์ ิสตช์ ดุ นเี้ ปน็ ลงิ คล์ ิสต์ทมี่ โี หนด
สดุ ทา้ ยอยู่ในตำแหน่งที่ 35 เป็นโหนดที่เกบ็ ข้อมลู U

โครงสร้างโหนดสว่ นหวั (Head Node Structure)
โดยท่ัวไปภายในโครงสรา้ งลิงค์ลสิ ต์ จะมีโหนดพิเศษท่ีไม่ได้ทำหน้าท่ีเก็บข้อมูลแต่จะทำหน้าท่ีช้ี
ตำแหน่งเป็นโหนดแรกและโหนดสุดท้ายเรียกว่า โหนด Dummy ถือเป็นโครงสร้างโหนดส่วนหัวเกิดข้ึน
หลงั จากที่ได้สร้างลิสต์ขึ้นมา โดยภายในจะบรรจุข้อมูลเก่ียวกับลิสต์ เรียกว่า Metadata เป็นขอ้ มูลท่ีไว้
อธิบายข้อมูลภายในลิสต์ เช่น ฟิลด์ Count ท่ีบรรจุค่าตวั เลขจำนวนเต็มเพ่ือบอกค่าจำนวนสมาชิกที่อยู่
ภายในลิสต์ในขณะน้นั ดงั ภาพประกอบท่ี 4.2

CCoouunnt t pHead List
Count <integer>
Head <pointer>

End List

ภาพประกอบที่ 4.2 โครงสรา้ งโหนดส่วนหวั (Head Node Structure)

โหนดส่วนหัว หรือ โหนด Dummy แบง่ ออกเป็น 2 ชนิดดังน้ี
1.โหนด Dummy ทม่ี ีหนึง่ พอยน์เตอร์ โหนดนี้จะเก็บพอยนเ์ ตอร์ Head (pHead)
เพยี งตัวเดยี วสำหรบั ช้ไี ปยังโหนดแรกของลิงค์ลสิ ต์ โดยเรียกโหนดนีว้ า่ โหนด Header ดงั นัน้ โครงสรา้ ง
ลิงคล์ ิสตท์ ใี่ ช้โหนด Dummy ท่มี หี นง่ึ พอยน์เตอร์ จะมีลักษณะดังภาพประกอบที่ 4.3

49

pHead Data Link Data Link
…… Null

โหนด Dummy

ภาพประกอบท่ี 4.3 ลิงค์ลิสต์ทใ่ี ชโ้ หนด Dummy ท่มี หี นงึ่ พอยน์เตอร์

โครงสรา้ งลงิ คล์ ิสต์ ที่ใชโ้ หนด Dummy ทีม่ หี นึ่งพอยน์เตอร์ กรณที ไ่ี มม่ ีข้อมลู ใด ๆ จะ
มีลกั ษณะดงั ภาพประกอบที่ 4.4

pHead

Null

โหนด Dummy

ภาพประกอบท่ี 4.4 ลงิ คล์ สิ ต์ท่ใี ช้โหนด Dummy ทม่ี ีหนึง่ พอยนเ์ ตอร์
กรณไี ม่มีข้อมลู ใดๆ ในลงิ ค์ลติ ส์

2. โหนด Dummy ทีม่ สี องพอยนเ์ ตอร์ โหนดแบบนี้จะเกบ็ พอยน์เตอร์ Head (pHead)
และ Tail (pTail) โดยทพ่ี อยน์เตอร์ Head (pHead) ทำหน้าท่ีชไ้ี ปยงั โหนดแรกของลิงค์ลิสต์ และพอยน์
เตอร์ Tail (pTail) ทำหนา้ ทชี่ ้ีไปยงั โหนดสดุ ทา้ ยของลงิ ค์ลิสต์ ดงั ภาพประกอบท่ี 4.5

Data Link Data Link Data Link

… Null

pHead pTail

โหนด Dummy

ภาพประกอบที่ 4.5 ลิงค์ลสิ ตท์ ่ีใช้โหนด Dummy ที่มีสองพอยนเ์ ตอร์

50

โครงสร้างลงิ คล์ สิ ต์ ทใี่ ช้โหนด Dummy ที่มสี องพอยนเ์ ตอร์ กรณที ่ไี มม่ ีข้อมูลใดๆ จะมี
ลกั ษณะดังภาพประกอบท่ี 4.6

pHead pTail

HNeualld TNauilll

โหนด Dummy

ภาพประกอบที่ 4.6 ลิงคล์ สิ ต์ที่ใชโ้ หนด Dummy ทม่ี หี นง่ึ พอยนเ์ ตอร์
กรณีไมม่ ขี ้อมูลใดๆ ในลงิ คล์ ติ ส์

โครงสร้างโหนดข้อมูล (Data Node Structure)
โหนดข้อมูลประกอบด้วยสว่ นของข้อมูล (Data) คือข้อมูลหรือสารสนเทศทสี่ ามารถนำไปใช้
ประโยชนไ์ ด้ และส่วนของลงิ ค์ (Link) คือตัวช้ี หรือพอยตเ์ ตอรท์ ี่ใช้สำหรบั เชือ่ มโยงไปยังโหนดถดั ไป
โดยข้อมูลทเี่ ก็บในลิงค์ลสิ ตน์ น้ั จะเปน็ ข้อมลู ชนิดใดก็ได้ข้นึ อยกู่ บั การนำไปประยุกต์ใช้ดังภาพประกอบ
ท่ี 4.7

CDoautnat Link Node
Data <Data Type>
Link <pointer>

End Node

ภาพประกอบที่ 4.7 โครงสร้างโหนดข้อมลู (Data Node Structure)

4.2 ประเภทของลิงค์ลิสต์
ลงิ ค์ลสิ ตส์ ามารถแบ่งออกไดเ้ ป็น 3 ชนดิ คอื
1. ลงิ คล์ ิสต์เด่ยี ว (Singly Linked List) ลักษณะของลิงคล์ ิสตเ์ ดี่ยวคอื ลงิ คล์ ิสต์ทีม่ ีทิศทาง

เดียว โดยแตล่ ะโหนดจะเก็บพอยนเ์ ตอร์เพียงตวั เดียวน้นั คือพอยนเ์ ตอร์ สำหรับช้ตี ำแหนง่ ของโหนด
ถัดไป (Link) และโหนดสุดทา้ ยจะเก็บค่า Null เท่าน้ัน ลงิ ค์ลิสตเ์ ด่ยี วแสดงไดด้ งั ภาพประกอบท่ี 4.8

51

pHead Data Link Data Link Data Link
10 20 30 Null

ภาพประกอบที่ 4.8 ตวั อย่างลงิ ค์ลิสต์เดย่ี ว

2. ลิงคล์ สิ ตค์ ู่ (Doubly Linked List) ลกั ษณะของลิงคล์ ิสตค์ ู่คือ ลิงคล์ สิ ต์ทีม่ ี 2 ทิศทาง
โดยแต่ละโหนดเกบ็ พอยน์เตอร์สองตัวสำหรับชตี้ ำแหน่งของโหนดถัดไป (Forward Pointer : F) และ
ตำแหนง่ ของโหนดท่ีอยกู่ ่อนหนา้ (Backward Pointer : B) แสดงไดด้ งั ภาพประกอบที่ 4.9

pHead B Data F B Data F B Data F
Null 30 20 30 Null

ภาพประกอบท่ี 4.9 ตัวอยา่ งลงิ ค์ลสิ ตค์ ู่

3. ลงิ คล์ สิ ต์วงกลม (Circular Linked List) ลักษณะของลิงค์ลิสต์วงกลมคือ ลงิ คล์ ิสต์ท่มี ี
การเช่อื มโยงเป็นวงกลม โดยพอยนเ์ ตอรข์ องโหนดสุดทา้ ยจะชีต้ ำแหน่งของโหนดแรกของลิงคล์ ิสตเ์ สมอ
ดังภาพประกอบท่ี 4.10 และภาพประกอบที่ 4.11

pHead Data Link Data Link
20
Head Pre 15

ภาพประกอบท่ี 4.10 ลิงค์ลสิ ต์เดยี่ วแบบวงกลม

pHead B Data F B Data F
15 20

ภาพประกอบที่ 4.11 ลิงค์ลิสต์คู่แบบวงกลม

52

4.3 ฟังก์ชนั การดำเนินงานบนลิงค์ลิสต์
การดำเนินงานบนลิงค์ลิสต์ประกอบด้วย 10 ฟังก์ชั่น ได้แก่ การสร้างลิงค์ลิสต์ (Create List) ,

การแทรกโหนด (Insert Node), การลบโหนด (Delete Node), การค้นหาข้อมูลภายในลิงค์
ลสิ ต์(Search List), การดึงขอ้ มูลออกจากโหนดมาใช้งาน (Retrieve Node), การตรวจสอบลิงคล์ ิสตว์ า่ ง
(Empty List), การตรวจสอบลิงค์ลิสต์เต็ม ( Empty List), การนับสมาชิกในลิงค์ลิสต์ (List Count),
การท่องเข้าไปในลิงคล์ ิสต์(Traverse List) และการยกเลิกการใช้งานลิงคล์ สิ ต์ (Destroy List) โดยแต่ละ
ฟังก์ช่ันสามารถอธิบายการทำงานโดยเขียนเป็นขั้นตอนวิธี และใช้รหัสทียม (Pseudo Code) อธิบาย
ขัน้ ตอนต่างๆ มีรายละเอียดดังนี้

1) การสร้างลิงค์ลิสต์ (Create List)
ฟังก์ชันการสร้างลิสต์เป็นการกำหนดโครงสร้างส่วนหัวและกำหนดค่าเร่ิมต้นให้กับ

Metadata สำหรับลิสต์ โดยในท่ีนี้จะมี Metadata 2 ตัวและสามารถขยายเพ่ิมเติมได้ซ่ึงเม่ือทำการ
สร้างลิสต์ข้ึนมา พอยน์เตอร์ Head (pHead) จะมีค่าเป็น Null เนื่องจากยังไม่มีข้อมูลภายในลิสต์
หมายถึง ลสิ ตว์ ่าง (Empty List) โดยมขี น้ั ตอนวธิ ีเขียนในรปู แบบรหสั เทียมดงั น้ี

Pseudo Code 4.1 : CreateList (list)
Initializes metadata for list.
Pre list is metadata structure passed by reference.
Post metadata initialized.
Step 1 allocate (list).
Step 2 set list head to null.
Step 3 set list count to 0.
Step 4 CreateList.

จาก Pseudo Code 4.1 แสดงการสรา้ งลสิ ตข์ น้ึ มาเพ่ือเตรียมการใช้งานไดด้ ังภาพ
ประกอบที่ 4.12

count pHead
0 Null

ภาพประกอบที่ 4.12 การสรา้ งสรา้ งลสิ ต์ขึน้ มาเพ่อื เตรยี มการใช้งาน

53

2) การแทรกโหนด(Insert Node)

เป็นฟงั กช์ นั ทใี่ ชส้ ำหรับแทรกโหนดใหมเ่ พมิ่ เขาไปในลสิ ต์ ในการแทรกโหนดแค่รู้เพียง

ว่าโหนดก่อนหน้า (Predecessor) ของโหนดใหม่ที่จะแทรกน้ันคือโหนดใด เม่ือได้รับการแจ้งว่าโหนด

กอ่ นหน้าคอื โหนดใดแลว้ ก็จะทำการแทรกข้อมลู เพม่ิ ตามขน้ั ตอนต่อไปนี้

1. จดั สรรหนว่ ยความจำสำหรบั โหนดใหม่พร้อมกับข้อมลู

2. กำหนดตำแหนง่ ตัวชี้ให้กบั โหนดใหม่

3. นำตัวชท้ี อ่ี ยกู่ ่อนหนา้ โหนดใหมช่ ี้มายงั โหนดใหม่

ดงั น้ันในการแทรกโหนดเขา้ ไปลิสตน์ น้ั ข้นั ตอนแรกจำเปน็ ตอ้ งรู้ตำแหนง่ ทีอ่ ยูข่ อง

โหนดก่อนหน้าโหนดใหม่ท่ีต้องการจะแทรกเสียก่อน ซ่ึงโหนดนี้จะระบุพอยน์เตอร์ซึ่งเป็นตัวชี้ตำแหน่ง

ของโหนดถัดไป (Link) โดยตัวช้ีน้ีสามารถเป็นได้สองสถานะด้วยกันคือ เป็นตัวช้ีที่อยู่ของโหนดถัดไป

หรือมีเป็นค่า Null ก็ได้ ในการแทรกระหว่างโหนดใดๆ จำเป็นต้องรู้ตำแหน่งโหนดก่อนหน้า เน่ืองจาก

โหนดใหมท่ ี่ทำการแทรกนี้จะมีพอยนเ์ ตอรช์ ้ีตำแหนง่ ของโหนดถดั ไป

สำหรับการแทรกโหนดเพิม่ เข้าไปในลิสต์สามารถกระทำได้ 4 รูปแบบด้วยกนั คือ

1. การแทรกโหนดในลสิ ต์วา่ ง

2. การแทรกโหนดทีต่ ำแหนง่ แรก

3. การแทรกโหนดระหว่างโหนดใดๆ

4. การแทรกโหนดทีท่ ้ายลสิ ต์

รูปแบบที่ 1 การแทรกโหนดในลสิ ตว์ ่าง (Insert into empty Linked List)

กรณีน้ีเป็นการแทรกโหนดเพ่ิมเข้าไปในลิสต์ในขณะท่ีลิสต์ว่างเปล่าหรือไม่มีข้อมูลใดๆ

อยู่ น่ันหมายถึงเป็นการแทรกสมาชิกตัวแรกเข้าไปซ่ึงขณะนั้นพอยน์เตอร์ Head (pHead) จะมีค่าเป็น

Null หลังจากน้ันก็มีลิสต์ใหม่ที่ต้องการแทรกเพ่ิมเข้ามา (pNew) ดังน้ันในกรณีน้ีจึงมีการเชื่อมโยงลิงค์

ระหวา่ งกนั สามารถเขยี นเปน็ ข้ันตอนวธิ ไี ดด้ งั น้ี

Pseudo Code 4.2 : Insert node into Empty Linked List

Set pNew link to list pHead. (Null Pointer)

Set list pHead to pNew. (First Node)

จากขนั้ ตอนวิธีขา้ งต้นแสดงถงึ การแทรกโหนดเข้าไปในลสิ ตใ์ นขณะที่ลิสต์วา่ งซง่ึ

ผลการกระทำดงั กล่าวก็จะได้ขอ้ มลู โหนดแรกภายในลิสต์ทเี่ ปน็ ไปดังภาพประกอบท่ี 4.13

54

count pHead 10 HeadNulPl re
0 HeadNulPl re

a) ก่อนแทรก ppNNeeww

count pHead

1 Head 10 HeadNulPl re

b) หลงั แทรก ppNNeeww

ภาพประกอบที่ 4.13 การแทรกโหนดเขา้ ไปในลสิ ตใ์ นขณะที่ลิสต์ว่าง

รปู แบบที่ 2 การแทรกโหนดท่ีตำแหน่งแรก (Insert new node at beginning of
Linked List)

กรณีนี้เปน็ การแทรกโหนดเข้าไปไว้ในตำแหน่งโหนดแรก ซึ่งทำให้โหนดที่เคยอยู่ลำดับ
แรกเดมิ มาตอ่ ทา้ ยโหนดใหมท่ แ่ี ทรกเขา้ ไป ข้นั ตอนแรกของการแทรกข้อมูลที่โหนดแรกของลิสต์ จะต้อง
ทราบถึงตัวช้ี (Pointer) ของตัวโหนดก่อนหน้า (Predecessor) ก่อน ที่เรียกว่า pPre ซึ่งหากไม่มีหรือมี
ค่าเป็น Null ก็หมายความว่าเป็นการแทรกโหนดแรกในลิสต์ว่างเปล่าเหมือนกับในกรณีแรกท่ีผ่านมา
นัน่ เอง

ข้ันตอนการแทรกโหนดที่ตำแหน่งแรกจะมีวิธีการคือ ให้นำตัวชี้ของโหนดใหม่ช้ีไปยัง
โหนดแรกของลิสต์ หลังจากนั้นก็ทำการกำหนดพอยน์เตอร์ Head (pHead) ชี้ไปยังโหนดใหม่ ซึ่งจะรู้
ตำแหน่งที่อยขู่ องโหนดใหม่อย่แู ล้วหลังจากทไ่ี ด้สรา้ งขึน้ โดยกำหนดให้ทอ่ี ย่ขู องโหนดแรกจะถูกจัดเกบ็ ท่ี
พอยนเ์ ตอร์ Head น่ันเอง โดยการแทรกโหนดท่ีตำแหน่งแรก แสดงได้ตามขัน้ ตอนวิธีดังตอ่ ไปนี้

Pseudo Code 4.3 : Insert new node at beginning of Linked List

Set pNew link to list pHead (To current first node)

Set list pHead to pNew (To new first node)

ดังนั้นการแทรกโหนดที่ตำแหนง่ แรกของลิสต์นั้นแสดงดังภาพประกอบที่ 4.14

55

count pHead 10 HeadNulPl re
1 Head

15 HeadnulPl re a) ก่อนแทรก

pNew 10 HeadNulPl re
count pHead

2 Head



15 Head Pre

pNew

b) หลงั แทรก

ภาพประกอบท่ี 4.14 การแทรกโหนดไวท้ ตี่ ำแหนง่ แรกของลิสต์

รูปแบบท่ี 3 การแทรกโหนดระหวา่ งโหนดใด ๆ (Insert new node into between
Node )

การแทรกระหวา่ งโหนดใดๆ ข้ันตอนแรกต้องรู้ตำแหนง่ โหนดกอ่ นหน้า (Predecessor)
ของโหนดท่ีต้องการแทรกเสียก่อน โดยความสำคัญของโหนดก่อนหน้า คือจะมีลิงค์ที่ใช้เชื่อมโยงไปยัง
โหนดถัดไปของโหนดท่ีต้องการแทรก ซ่ึงลิงค์น้ีเองท่ีจะนำไปแทนตำแหน่งตัวช้ีของโหนดใหม่ เพื่อจะได้
กำหนดตัวช้ีของโหนดใหม่ช้ีไปยังโหนดหลัง (Successor) ได้ ซ่ึงจะทำให้โหนดใหม่แทรกอยู่ระหว่าง
โหนดใดๆ ได้ ในการแทรกระหว่างโหนดใดๆ ตัวช้ีหรือลิงค์ฟิลด์ของโหนดใหม่จะชี้ไปยังโหนดหลัง
(Successor) ในขณะท่ีตัวชี้ pPre ก็จะชี้ไปโหนดใหม่ ซ่ึงมีขั้นตอนวิธีในการแทรกโหนดระหว่างโหนด
ใดๆ ดงั ต่อไปน้ี

Pseudo Code 4.4 : Insert new node into between Node

Set pNew link to pPre link. (New to successor)

Set pPre link to pNew. (Predecessor to new)

ดงั น้นั การแทรกโหนดระหวา่ งโหนดใด ๆ ของลสิ ต์น้นั แสดงดังภาพประกอบที่ 4.15

56

count pHead 15 Head Pre 10 HeadNull
2 Head

pPre 5 Head Pre a) ก่อนแทรก
pNew

count pHead 15 Head Pre 10 HeadNull
3 Head
 
pPre
5

pNew b) หลังแทรก

ภาพประกอบท่ี 4.15 การแทรกโหนดระหว่างโหนดใด ๆ

รูปแบบท่ี 4 การแทรกโหนดท่ีท้ายลิสต์ (Insert new node at the end of Linked
List)

เมอื่ มกี ารเพิม่ โหนดทสี่ ว่ นทา้ ยของลสิ ต์ ตอ้ งการเพยี งแคต่ วั ชี้โหนดกอ่ นหน้า
(Predecessor) เพ่ือช้ีไปยังโหนดใหม่เท่านั้น ซ่ึงในท่ีน้ีจะไม่มีโหนดหลัง(Successor) เนื่องจากเป็นการ
แทรกโหนดใหมท่ ่ีท้ายลิสต์ ดังน้นั ส่วนท่จี ัดเก็บพอยนเ์ ตอร์เก็บคา่ อ้างองิ ไปยังทอ่ี ยู่ของโหนดถัดไป ของ
โหนดใหมจ่ งึ ถกู กำหนดใหเ้ ป็นค่า Null โดยชุดคำสั่งท่ีใช้ในการแทรกโหนดที่ส่วนทา้ ยลสิ ต์ สามารถเขียน
ขน้ั ตอนวธิ ีไดด้ ังน้ี

Pseudo Code 4.5 : Insert new node at the end of Linked List

Set pNew link to null pointer.

Set pPre link to pNew. (Predecessor to new)

ดังนั้นการแทรกโหนดที่ทา้ ยลิสต์แสดงดังภาพประกอบท่ี 4.16

57

count pHead 5 10 Null
3 Head 15

pPre 25

count pHead pNew a) ก่อนแทรก
4 Head 15
5 10 

pPre 25 Null 

pNew b) หลังแทรก

ภาพประกอบท่ี 4.16 การแทรกโหนดไว้ท่ีทา้ ยลิสต์

จากรายละเอียดการแทรกโหนดเข้าไปลสิ ต์ในรปู แบบต่างๆ ไมว่ า่ จะเป็นการแทรก
โหนดในขณะท่ีลิสต์ว่าง การแทรกโหนดที่ตำแหน่งแรกของลิสต์ การแทรกโหนดใหม่ระหว่างโหนดใดๆ
หรือการแทรกท้ายลิสต์ก็ตาม ข้นั ตอนวิธที ี่จะกล่าวต่อไปน้ีที่ใช้สำหรับการแทรกโหนดเข้าไปในลิสต์ โดย
จะมีพอยน์เตอรช์ ้ีไปยังลิสตซ์ ึ่งเป็นโหนดก่อนหนา้ (Predecessor) และข้อมูลทต่ี ้องการแทรกซงึ่ จะตอ้ งมี
การจดั สรรหน่วยความจำสำหรับโหนดใหม่ และทำการปรบั เปลีย่ นพอยน์เตอรเ์ ชอื่ มโยงที่เหมาะสมต่อไป
เมื่อทำตามข้ันตอนวิธีน้ีเรียบร้อยแล้วจะทำการคืนค่าการทำงานเป็นค่าตรรกะที่เป็นจริงเมื่อแทรกโหนด
ใหม่ได้ ในขณะเดียวกันจะคืนค่าตรรกะที่เป็นเท็จเม่ือมีหน่วยความจำไม่เพียงพอสำหรับการเพ่ิมโหนด
ใหม่ ซ่ึงก็คือข้อผิดพลาดในสถานะ Overflow น่ันเอง โดยข้ันตอนวิธีของการแทรกโหนดจะแสดงได้
ดงั ตอ่ ไปน้ี

Pseudo Code 4.6 : Algorithm Insert Node (list, pPre, dataIn)
Inserts data into a new node in the list.
Pre list is metadata structure to a valid list.

pPre is pointer to data’s logical predecessor.
dataIn contains data to be inserted.
Post data have been inserted in sequence.
Return true if successful. False if memory overflow.

58

Step 1 Allocate (pNew).
Step 2 Set pNew data to dataIn.
Step 3 If (pPre = null)

Adding before first node or to empty list.
a) Set pNew link to list head.
b) Set list head to pNew.
Step 4 else
Adding before first node or to empty list.
a) Set pNew link to pPre link.
b) Set pPre link to pNew.
Step 5 End If. [End of If Structure]
Step 6 Return true. [End of Program]

3) การลบโหนด (Delete Node)
ขัน้ ตอนวธิ สี ำหรบั การลบโหนดออกจากลิสต์ นอกจากจะนำโหนดท่ีถูกลบสง่ คืนแกห่ น่วย

ความจำระบบเพ่อื ให้ระบบสามารถนำหนว่ ยความจำไปใช้งานอน่ื ตอ่ ไปแลว้ ยงั ต้องมกี ารปรับเปลีย่ นตัวชี้
ใหม่ด้วย สำหรับข้ันตอนแรกของการลบโหนด จะต้องค้นหาตำแหน่งของโหนดท่ีต้องการลบ (pLoc)
ภายในลิสต์ให้พบก่อน เมื่อพบตำแหน่งโหนดท่ีต้องการลบภายในลิสต์แล้วจะทำให้ทราบตำแหน่งท่ีอยู่
ของโหนดก่อนหน้าที่ต้องการลบ (Predecessor) หลังจากน้ันก็จะกำหนดพอยต์เตอร์ชี้ตำแหน่งของ
โหนดก่อนหน้าให้ช้ีไปยังโหนดหลัง (Successor) ของโหนดท่ีต้องการลบ จากนั้นก็จะนำพ้ืนที่
หนว่ ยความจำที่เก็บโหนดที่ถกู ลบไปนัน้ ส่งคนื แก่ระบบเพอื่ นำไปใชง้ านอ่ืนต่อไป

สำหรับการลบโหนดออกจากลิสต์สามารถกระทำได้ 3 รปู แบบดว้ ยกันคอื
1. การลบโหนดทต่ี ำแหนง่ แรกของลงิ คล์ ิสต์
2. การลบโหนดใดๆ ของลิงค์ลสิ ต์
3. การลบโหนดสดุ ทา้ ยของลิงค์ลิสต์
รปู แบบท่ี 1 การลบโหนดทตี่ ำแหน่งแรกของลงิ ค์ลิสต์ (Delete First Node of
Linked List)
ในกรณีลบโหนดที่อยู่ลำดับแรกของลสิ ต์ เมื่อรตู้ ำแหนง่ โหนดแรก ซ่ึงเปน็ โหนดที่
ต้องการลบ (pLoc) กใ็ ห้ทำการรเี ซตพอยน์เตอร์ Head (pHead) เพ่ือให้ช้ีไปยังโหนดหลงั (Successor)
ท่ีอยู่ถดั จากโหนดแรกที่ต้องการลบ จากน้ันก็จะนำโหนดท่ีถกู ลบสง่ คืนแก่ระบบ และเนื่องจากในที่น้ีเป็น
การลบโหนดแรกออกจากลิสต์ ตัวโหนดก่อนหน้า (Predecessor) จึงไม่มี ดังน้ันโหนดโหนดก่อนหน้า

59

จึงถูกกำหนดค่าให้เป็น Null หมายถึง เป็นการลบโหนดท่ีตำแหน่งแรกนั่นเอง ในกรณีท่ีเป็นการลบ
โหนดลำดับแรกออกจากลิสต์และถ้าโหนดแรกน้ันเป็นเพียงโหนดเดียวท่ีอยู่ในลิสต์ หลังจากท่ีถูกลบ
ออกไปพอยนเ์ ตอร์ Head (pHead) จะถกู กำหนดให้เปน็ คา่ Null ซึง่ ถือวา่ เป็นลิสตว์ า่ งไปโดยปรยิ าย

สำหรับประโยคคำส่ังที่ใช้ลบโหนดในตำแหน่งแรกออกจากลสิ ตไ์ ด้แสดงไว้ในขัน้ ตอนวธิ ี
ท่ีจะกล่าวต่อไปนี้ สังเกตได้ว่าจะมีคำส่ัง Recycle ด้วย ซึ่งคำส่ังนี้เป็นคำส่ังท่ีใช้สำหรับคืนค่าโหนดท่ีถูก
ลบไปส่งคืนแก่ระบบเพื่อให้หน่วยความจำไดนามิกนำไปใช้งานอ่ืนได้ต่อไป สามารถเขียนขั้นตอนวิธีได้
ดังน้ี

Pseudo Code 4.7 : Delete First Node of Linked List.
Set list pHead to pLoc link.
Recycle (pLoc).
ดังน้นั การแทรกโหนดทท่ี ้ายลิสตแ์ สดงดังภาพประกอบท่ี 4.17

count pHead 5 10 Null
3 Head 15 10 Null

count pHead pLoc a) ก่อนลบ

2 Head Recycled 5

pLoc b) หลังลบ

ภาพประกอบที่ 4.17 การลบโหนดลำดับแรกออกจากลิสต์

รปู แบบท่ี 2 การลบโหนดใด ๆ ของลิงคล์ ิสต์ (Delete Node of Linked List)
สำหรับกรณีการลบโหนดใดๆ ออกจากลิสต์ ประกอบด้วยการลบโหนดท่ีอยู่ระหว่าง
โหนดสองโหนดภายในลิสต์ และการลบโหนดสุดท้ายของลิงค์ลิสต์ ท้ังสองกรณีแม้ว่าจะมีความแตกต่าง
กันแต่กส็ ามารถใชต้ รรกะเดยี วกันในการใช้งาน
ข้ันตอนแรกจำเป็นต้องรู้ตำแหนง่ โหนดทีต่ อ้ งการลบเสียก่อน จากน้ันกก็ ำหนดตัวช้ขี อง
โหนดก่อนหนา้ (Predecessor) ให้ช้ีไปยงั โหนดหลงั (Successor) ที่อยู่ถัดจากโหนดท่ีต้องการลบนน่ั เอง
สามารถเขยี นขน้ั ตอนวิธีไดด้ งั นี้

60

Pseudo Code 4.8 : Delete Node of Linked List
Set pPre link to pLoc link.
Recycle (pLoc).

ขัน้ ตอนการลบโหนดใดๆ ของลิงคล์ ิสต์ดังภาพประกอบที่ 4.18

count pHead 5 10 Null
3 Head 15

pPre pLoc

count pHead a) ก่อนลบ

2 Head 15 Recycle 10 Null
d

pPre pLoc

b) หลงั ลบ

ภาพประกอบที่ 4.18 การลบโหนดออกจากลงิ คล์ ิสต์

รปู แบบที่ 3 การลบโหนดสดุ ท้ายของลิงคล์ ิสต์ (Delete last node in Linked List)
สำหรบั กรณี การลบโหนดสดุ ทา้ ยของลิสตอ์ อก สามารถทำการลบโหนดสดุ ท้ายไดเ้ ลย
เมือ่ โหนดสุดทา้ ยของลิสต์ไดถ้ กู ลบออกไปแล้ว คา่ ของ Null Pointer ก็จะถกู ย้ายไปเกบ็ ไวใ้ นตำแหน่งตัว
ช้ีโหนดก่อนหน้า(Predecessor) ดังนั้นโหนดท่ีเคยอยู่ก่อนหน้าก็จะกลายเป็นโหนดในลำดับสุดท้าย
ส่วนโหนดสุดท้ายของลิสต์ท่ีถูกลบไปก็จะส่งคืนกลับไปยังระบบ สำหรับข้ันตอนวิธีในการลบโหนด
สุดทา้ ยของลงิ คล์ สิ ต์แสดงไดด้ ังน้ี

Pseudo Code 4.9: Deletion last node in Linked list
Set pPre link to null pointer.
Recycle (pLoc).
แสดงข้นั ตอนการลบโหนดสุดทา้ ยของลิสต์ดังภาพประกอบที่ 4.19

61

count pHead a) กอ่ นลบ

3 Head 15 5 10 Nu
ll

pPre pLoc

count pHead b) หลงั ลบ

2 15 5 Null Recycled

pPre pLoc

ภาพประกอบที่ 4.19 ขั้นตอนการลบโหนดสดุ ทา้ ยของลิงค์ลสิ ต์

ขัน้ ตอนวิธีสำหรบั การลบโหนดทตี่ ำแหน่งแรกของลิงค์ลิสต์และการลบโหนดใด ๆ
ของลิงคล์ ิสต์ แสดงไดด้ งั น้ี

Pseudo Code 4.10 : Algorithm Delete (list ,pPre ,pLoc,dataOut )
Deletes data from list & returns it to calling module.
Pre list is metadata structure to a valid list.

pPre is pointer to predecessor node.
dataOut is variable to receive deleted data.
Post data have been deleted and returned to caller.
Step 1 Move pLoc data to dataOut.
Step 2 If (pPre = null)

Deleting first node.
Set list head to pLoc link.
Step 3 else
Deleting other nodes.
Set pPre link to pLoc link.
Step 4 End If. [End of If Structure]
Step 5 Recycle (pLoc).
Step 6 End. [End of deleteNode]

62

4) การคน้ หาข้อมูลภายในลงิ ค์ลิสต์ (Search List)
ในการคน้ หาขอ้ มลู ภายในลิงคล์ ิสต์ ตามปกตแิ ล้วสามารถค้นหาขอ้ มูลภายในลิงคล์ ิสต์ได้

หลายกรณี เช่น การแทรกโหนด การลบโหนดออกจากลิงค์ลิสต์ การดึงข้อมูลจากลิงค์ลิสต์ ล้วนแต่
ต้องการการค้นหาข้อมูลก่อนการกระทำดังกล่าวเสมอ ดังน้ันการค้นหาข้อมูลภายในลิงค์ลิสต์ มี 2 วิธี
คือ 1) ค้นหาข้อมูลแบบเรียงลำดับข้อมูล (Sequential Search) หรือเรียกอีกอย่างว่า Ordered List
Search 2) การค้นหาแบบไบนารีเสร์ิซ (Binary Search) เป็นการค้นหาข้อมูลภายในลิสต์ที่สร้างด้วย
อาเรย์

หลักการคน้ หาข้อมูลในลิงคล์ สิ ตจ์ ะใช้คีย์ (Key )เป็นตวั ค้น โดยจะมคี ยี ฟ์ ลิ ด์ทใี่ ช้สำหรับ
เปรียบเทียบกับข้อมูลที่ต้องการค้นหา ซ่ึงโดยปกติลิงค์ลิสต์อย่างง่ายน้ัน คีย์และข้อมูลสามารถเป็นฟิลด์
เดยี วกนั ได้

ดงั นัน้ เริม่ แรกของการคน้ หาจะต้องกำหนดคีย์ทตี่ ้องการคน้ หาใหไ้ ด้กอ่ น หรือท่เี รยี กวา่
Target key โดยการค้นหาภายในลิสต์แบบเรียงลำดับข้อมูล จะทำการค้นหานับต้ังแต่โหนดแรกไป
จนกระทั่งข้อมูลภายในลิสต์ตรงกับค่า Target Key แล้วจึงคืนคา่ ตรรกะเป็นจริงกลับไปในขณะที่หากไม่
สามารถจับคู่กบั คีย์ไดก้ ็จะคืนค่าตรรกะทเ่ี ปน็ เท็จกลบั ไป

หลกั การในการค้นหาข้อมูลภายในลงิ คล์ ิสต์จะพจิ ารณาจากโหนดก่อนหน้า (pPre)
และนำตำแหน่งของพอยน์เตอรป์ ัจจุบัน (pLoc) มาเปรียบเทียบข้อมลู กนั โดยผลลัพธ์จากการเปรียบ
เทยี บจะมีการคนื คา่ ตรรกะเป็นจรงิ เมือ่ พบข้อมลู และคืนค่าตรรกะเป็นเท็จเม่ือไม่พบขอ้ มูล ซ่งึ เงอื่ นไข
ดงั กล่าวจะถูกกำหนดไว้ตามกฎเกณฑ์อย่างเหมาะสมดังตารางท่ี 4.1

ตารางท่ี 4.1 ผลลัพธ์การค้นหาขอ้ มูลภายในลิงคล์ ิสต์

เงอื่ นไข ตำแหน่งตัวก่อนหน้า ตำแหนง่ ทค่ี น้ หา คืนคา่
(Return)
(Condition) (pPre) (pLoc) False

Target < first node Null First node True
False
Target = first node Null First node True
True
first < Target < last Largest node < target First node > target False

Target = middle node Node’s predecessor Equal node

Target = last node Last’s predecessor Last node

Target > last node Last node Null

63

สำหรบั ขัน้ ตอนวิธใี นการค้นหาขอ้ มลู ในลงิ ค์ลสิ ต์ แสดงไดด้ ังนี้
Pseudo Code 4.11 : Searching List
Algorithm searchList (list,pPre,pLoc,target)
Searches list and passes back address of node containing.
Pre list is metadata structure to a valid list.

pPre is pointer variable for predecessor.
pLoc is pointer variable for current node.
target is the key being sought.
Post pLoc points to first node with egual/greather key.
-or- null if target > key of last node.
pPre points to largest node smaller than key.
-or- null if target < key of first node.
Return true if found, false if not found.
Step 1 Set pPre to null.
Step 2 Set pLoc to list head.
Step 3 [loop] [ (pLoc not null AND target > pLoc key)

Set pPre to pLoc.
Set pLoc to pLoc link.
[End loop]
Step 4 If (pLoc = null)
Set return value.
Set found to false.
Step 5 else If (target = pLoc key)
set found to true.
Step 6 else
set found to false.
Step 7 End If. [ End of If Structure]
Step 8 Return found.
Step 9 End searchList. [End of Program]

64

5) การดงึ ข้อมูลออกจากโหนดมาใชง้ าน (Retrieve Node)
วิธกี ารดึงข้อมูลออกจากโหนดเพ่อื นำออกมาใช้งานน้นั จะเร่ิมตน้ ด้วยการค้นหาโหนดจาก

ตำแหนง่ ข้อมูลภายในลิสต์ ถ้าหากพบข้อมูลที่ต้องการก็จะทำการเคลื่อนย้ายขอ้ มลู ไปยังพื้นที่เอาต์พุตใน
ส่วนของโมดูลท่ีเรียกใช้งาน และจะคืนค่าตรรกะเป็นจริงกลับไป แต่ถ้าไม่พบก็จะคืนค่าตรรกะเป็นเท็จ
กลบั ไป สำหรับขนั้ ตอนวิธกี ารดงึ ขอ้ มลู จากโหนดมาใช้งานแสดงไดด้ งั น้ี

Pseudo Code 4.12 : Algorithm for retrieve node from Linked List
Algorithm retrieveNode (list , key , dataOut)
Retriveves data from a list.
Pre list is metadata structure to a valid list.

Key is target of data to be retrieved.
dataOut is variable to receive retrieve data.
Post data placed in dataOut.
-or-error returned if not found.
Return true if successful, false if data not found.

Step 1 Set found to searchList (list, pPre, pLoc ,key)
Step 2 If (found)

move pLoc data to dataOut.
Step 3 End If. [End of If Structure]
Step 4 Return found.
Step 5 End retrieve Node. [End of Program]

6) ลิสตว์ ่าง (Empty List)
เป็นฟงั ก์ชันทใี่ ชต้ รวจสอบว่าภายในลสิ ต์วา่ งหรือไม่ ซึง่ เปน็ โมดลู แบบงา่ ยท่ีคืนค่า

ตรรกะ ณ ขณะนั้นกลับไป เช่น คืนค่าตรรกะเป็นจรงิ กลบั ไปเมื่อลสิ ต์ว่าง หรือในทางตรงกันข้ามก็จะคืน
ค่าตรรกะเท็จกลบั ไปเป็นตน้ มขี น้ั ตอนวธิ ีดังนี้

Pseudo Code 4.13 : Algorithm emptyList (list)
Returne Boolean indicating whether the list is empty.
Pre list is metadata structure to a valid list.
Return true if list empty, false if list contains data.

65

Step 1 If (list count =l 0)
return true.

Step 2 else
return false

Step 3 End emptyList. [End of Program]

7) ลสิ ต์เต็ม (Full List)
เป็นฟังก์ชันท่ีใช้ตรวจสอบว่าภายในลิสตน์ ้ันเต็มหรือไม่ ซึง่ ก็จัดเป็นโมดูลแบบง่ายเชน่ กัน

ด้วยการคืนค่าตรรกะในขณะนั้นกลับไป ฟังก์ชันน้ีอาจไม่จำเป็นต้องใช้ก็ได้ โดยเฉพาะในภาษา C
เนอื่ งจากลิงคล์ ิสตใ์ ชห้ น่วยความจำแบบไดนามิก โดยรายละเอียดข้นั ตอนวิธีแสดงได้ดังนี้

Pseudo Code 4.14 : Algorithm fullList (list)
Returns Boolean indicating whether or not the list is full.
Pre list is metadata structure to a valid list.
Return false if room for new node , true if memory full.
Step 1 If (memory full)

return true.
Step 2 else

return false.
Step 3 End If. [End of If Structure]
Step 4 Return true.
Step 5 End fullList. [ End of program]

8) การนับสมาชกิ ในลิงคล์ สิ ต์ (List Count)
การนับสมาชิกในลิงคล์ สิ ต์จะมเี พียงคำสงั่ เดยี วเทา่ นนั้ และเป็นฟังกช์ ันทมี่ คี วามสำคัญ

เพราะเป็นฟังก์ชั้นท่แี จ้งจำนวนสมาชิกหรือจำนวนอีลีเมนต์ในลิงค์ลสิ ต์ใชใ้ นการนับจำนวนสมาชิกตอนท่ี
เข้าไปทอ่ งลิงคล์ ิสต์ สามารถเขียนเป็นข้ันตอนวธิ ีได้ดังต่อไปน้ี

Pseudo Code 4.15 : Algorithm listcount (list).
Return integer representing number of nodes in list.
Pre list is metadata Structure to a valid list.
Return count of number of nodes in list.

66

Step 1 Return (list count).
Step 2 End listcount. [End of Program]

9) การทอ่ งเข้าไปในลิสต์ (Traverse List)
ขนั้ ตอนวธิ ีการท่องเข้าไปในลสิ ต์ จะเรมิ่ ต้นที่โหนดแรกและสแกนไปทีละโหนดจนกระทั่ง

ส้ินสุดที่โหนดสุดท้าย ตรรกะของการท่องเข้าไปในลิสต์น้ัน สามารถใช้ขั้นตอนวิธีเพื่อการกระทำกับ
ข้อมูลทอ่ี ยู่ในลิงค์ลสิ ต์ได้หลากหลาย เช่น การเปล่ียนแปลงค่าในแต่ละโหนด การพมิ พข์ ้อมูลภายในลสิ ต์
การคำนวณหาผลรวมของฟลดภ์ ายในลิสต์ การคำนวณหาคา่ เฉล่ยี

สำหรับการท่องเข้าไปในลิสต์ จะต้องมีการกำหนดตัว Walking Pointer เพื่อให้พอยน์
เตอร์น้ีเคล่ือนที่จากโหนดไปยังโหนดในแต่ละอีลีเมนต์ และมีการกำหนดการวนรอบ (Loop) เพื่อให้
พอยน์เตอร์เคลื่อนท่ีไปยังโหนดถัดไปในลักษณะเรียงลำดับภายในลิสต์ ข้ันตอนวิธีการกำหนดตัว
Walking Pointer และรอบการทำงาน แสดงไดด้ ังนี้

Pseudo Code 4.16 : Set waling pointer of Linked list.
Step 1 Set pWalke to list head.
Step 2 Loop (more nodes)

Process (pWalker data)
Set pWalker to next link.
Step 3 End loop.

จาก Pseudo Code 4.16 เร่ิมตน้ จากการตดิ ต้ัง Walking Pointer น้ีท่โี หนดแรก
ภายในลสิ ต์ แล้วใชล้ ปู เพื่อการประมวลผลด้วยการให้ท่องไปทลี่ ะโหนดเป็นลำดับไปเรื่อยๆ จนกระทัง่
ท่องไปยังโหนดสุดท้าย การทำงานในแต่ละลูปจะมีการเรียกใช้โมดูลเพ่ือประมวลผลทุกครั้งและส่งค่า
ขอ้ มูลกลับไปในขณะที่ Walking Pointer ท่องไปยงั แตล่ ะโหนดและเม่ือประมวลผลจนกระท่ังถึงโหนด
สุดทา้ ยก็จะสิน้ สุดการทำงานของลูป

สำหรบั ขน้ั ตอนวธิ ีการท่องเขา้ ไปในลงิ ค์ลสิ ต์ ในทน่ี ี้ได้ตง้ั ช่ือวา่ getNext อนั เนือ่ งมา
จากในการท่องเข้าไปในลสิ ต์แต่ละคร้ัง ต้องมีการเขา้ ถึงโหนดตัวถัดไปนั่นเอง

Pseudo Code 4.17 : Algorithm getNext (list , fromWhere, dataOut)
Traverses a list. Each call returns the location of an element in the list.
Pre list is metadata structure to a valid list.

fromWhere is 0 to start at the first element.
dataOut is reference to data variable.

67

Post dataOut contains data and true returned -or- if end of list.
Returns false.

Return true if next element located.
False if end of list.

Step 1 If (empty list)
return false.

Step 2 If (fromWhere is beginning) [Start from first]
(a) set list pos to list head.
(b) move current list data to dataOut.
(c ) return true.

Step 3 else Continue from pos
If (end of list) [End of List]
return false.
else
(a) set list pos to next node.
(b) move current list data to dataOut.
(c ) return true.
End If.

Step 4 End If. [ End of If Structure]
Step 5 End getNext. [End of Program]

10) การยกเลิกการใช้งานลิงคล์ ิสต์ (Destroy List)
เมื่อไม่ต้องการใช้งานลิงค์ลิสต์อีกต่อไปจะใช้ฟังก์ชัน Destroy List ดำเนินการลบโหนด

ทุกโหนดที่ยังคงอยู่ภายในลิงค์ลิสต์ออกไปทั้งหมดและส่งคืนหน่วยความจำแก่ระบบเพื่อนำไปใช้งานอื่น
ไป ซ่ึงคำสั่งการยกเลิกการใช้งานลงิ ค์ลิสต์ สามารถแสดงข้นั ตอนวธิ ีได้ดงั น้ี

Pseudo Code 4.18 : Algorithm destroyList (pList)
Deletes all data in list.
Pre list is metadata structure to a valid list.
Post all data deleted.
Step 1 Loop (not at end of list)

Set list head to successor node.
Release memory to heap.

68

Step 2 End loop.
No data left in list. Reset metadata.

Step 3 Set list pos to null.
Step 4 Set list count to 0.
Step 5 End destroyList. [End of Program]

4.4 ลิงค์ลิสต์ชนิดอ่นื ๆ
นอกจากลิงค์ลสิ ต์เดี่ยวมีข้อกำจัดคือไม่สามารถท่องไปยังลิสต์ในลกั ษณะจากหลังไปหน้าได้ การ

เข้าไปดำเนินการใดๆ ภายในลิงค์ลิสต์เด่ียวจึงต้องเร่ิมต้นจากโหนดแรกไปยังโหนดสุดท้าย และไม่
สามารถเดนิ แบบยอ้ นกลับ

ดังน้ันจึงมีการสร้างลงิ ค์ลิสต์ชนิดอื่นๆ ซึง่ มคี วามซับซ้อนมากกว่าลิงค์ลิสตเ์ ดี่ยว โดยในที่นี้จะขอ
กลา่ วถงึ ลิงคล์ สิ ต์ประเภทตอ่ ไปนี้

1. ลิงค์ลิสต์แบบวงกลม (Circular-Linked List)
2. ลิงคล์ ิสต์คู่ (Double-Linked List)
ลิงค์ลิสต์แบบวงกลม (Circular-Linked List) ตามปกติแล้วลิงค์ลิสต์เด่ียว พอยน์เตอร์ของ
โหนดสุดท้ายจะถูกกำหนดให้เป็นคา่ Null ซึ่งหมายถึงเป็นโหนดสุดท้ายภายในลสิ ต์ แต่สำหรับลงิ ค์ลิสต์
แบบวงกลมโหนดสุดท้ายนจ้ี ะเช่ือมโยงไปยังโหนดแรกของลิงค์ลิสต์ และด้วยการเช่ือมโยงดังกล่าวจึงทำ
ให้ลิงค์ลิสต์แบบวงกลมสามารถเข้าถึงโหนดส่วนกลางของลิสตไ์ ด้โดยไมจ่ ำเป็นต้องเร่ิมจากต้นลิสต์เสมอ
ไป ดังภาพประกอบท่ี 4.10 ถึง ภาพประกอบท่ี 4.11 ในกรณีแรกโหนดหรือลบโหนดออกจากลิงค์ลิสต์
แบบวงกลมจะมรี ปู แบบเชน่ เดยี วกนั กับลงิ ค์ลสิ ต์เดยี่ ว ยกเว้นเพียงแตต่ วั ช้ีของโหนดสุดท้ายเทา่ น้นั ที่จะชี้
กลับไปยังโหนดแรก ส่วนกรณีการแทรกหรือลบโหนดที่ตำแหน่งท้ายจะต้องมีปรับปรุงฟิลด์ Rear ซึ่ง
บรรจภุ ายในโครงสร้างของโหนดส่วน สำหรับโหนดตำแหนง่ ท้ายทีไ่ ดร้ ับการแทรกหรือลบโหนดออกไปก็
จะตอ้ งปรบั ปรงุ ลงิ คใ์ หมเ่ พ่ือเชอื่ มโยงลงิ ค์ฟิลด์ไปยังโหนดแรกเสมอ
ลงิ ค์ลิสต์คู่ (Double-Linked List) ลิงค์ลิสต์คู่ จัดเปน็ ลงิ ค์ลิสต์ประเภทหน่งึ ท่มี ีความสามารถ
สูงทีเดียวกล่าวคือ ในแต่ละโหนดจะประกอบไปด้วยพอยนเ์ ตอรอ์ ยู่ 2 ตัว โดยตัวแรกจะใชส้ ำหรับช้ไี ปยัง
ตัวถัดไป (Successor) และอีกตัวหนึ่งจะชี้ไปยังตัวก่อนหน้า (Predecessor) ภายในโครงสร้างโหนด
สว่ นหัว จะประกอบไปด้วยขอ้ มูล 3 ฟิลดค์ ือ ตัวนบั (count) ตำแหน่งพอยน์เตอร์ Head (pHead) และ
พอยน์เตอร์ฟิลด์ Rear โดยถึงแม้ว่าฟิลด์ Rear อาจไม่จำเป็นต่อการใช้งานสำหรับลิงค์ลิสต์คู่ก็ตาม แต่
อาจจำเป็นต้องนำมาใช้งานในบางครั้ง โดยเฉพาะการแทรกและการค้นหา ซ่ึงจะทำให้เกิดประสิทธิภาพ
ยง่ิ ข้ึน
แต่ละโหนดของลิงค์ลิสต์แบบสองทาง จะบรรจุตัวช้ีหรือพอยน์เตอร์อยู่สองตัวคือ Backward
Pointer ที่ช้ีไปข้างหลัง ซึ่งก็คือตัวก่อนหน้า (Predecessor) ในขณะท่ี Forward Pointer จะชี้ไปยัง

69

ข้างหน้าซ่ึงก็คือตัวถัดไป (Successor) โดยท้ังสองจะใช้อักษรย่อแทนว่า B และ F ท่ีแสดงไว้ใน
ภาพประกอบท่ี 4.9

นอกจากน้ียังมีลิงค์ลิสต์คู่อีกชนิดหนึ่งซึ่งก็คือ ลิงค์ลิสต์คู่แบบวงกลม (Double-Linked
Circular-Linked List) ซึ่งเป็นการนำข้อดีของลิงค์ลิสต์สองคู่มารวมกับลิงค์ลิสต์แบบวงกลม โดย
Forward Pointer ของโหนดสุดท้ายจะชี้ไปยังโหนดแรกของลิสต์และ Backward Pointer ของโหนด
แรกก็จะชี้ไปยังโหนดสุดท้าย แต่ถ้าในกรณีที่มีเพียงโหนดเดียวภายในลิสต์ พอยน์เตอร์ท้ังแบบ
Forward และ Backward ก็จะชก้ี ลบั ไปยังโหนดของตวั เอง

1) การแทรกโหนดในลงิ ค์ลิสต์คู่
สำหรบั การแทรกโหนดในลงิ คล์ ิสตค์ นู่ น้ั สามารถทำได้ 2 รูปแบบคือ การแทรก

โหนดเมื่อลิงค์ลิสต์ว่างหรอื แทรกโหนดตำแหน่งแรก และการแทรกโหนดในลิงค์ลิสต์คู่ระหว่างสองโหนด
ใดๆ มขี น้ั ตอนการแทรกโหนดในลงิ ค์ลิสตค์ ูแ่ สดงได้ดังน้ี

Pseudo Code 4.19 : Algorithm insertDbl (list dataIn)
This algorithm inserts data into a double-linked list.
Pre list is metadata structure to a valid list.

dataIn contains the data to be inserted.
Post the data have been inserted in sequence.
Return 0 : failed –dynamic memory ; memory overflow

1 : successful.
2 : failed-duplicate key presented.
Step 1 If (full list)

return 0.
Step 2 End if

Locate insertion point in list.
Step 3 Set found to searchList (list,predecessor,successor,dataIn key)
Step 4 If (not found)

allocate new node.
move dataIn to new node .
If (predecessor is null)

Inserting before first node or into empty list.
1 set new node back pointer to null.
2 set new node fore pointer to list head.
3 set list head to new node.

70

else
Inserting new into middle or end of list.
1 set new node fore pointer to predecessor
2 set new node back pointer to predecessor.

end if
Test for insert into null list or at end of list.
If (predecessor fore null)

Inserting at end of list-set rear pointer.
set list rear to new node.
else
Inserting in middle of list- point successor to new.
set successor back to new node.
end if
set predecessor fore to new node.
return 1.
Step 5 end if
Duplicate data Key already exists.
Step 6 return 2.
Step 7 End insertDbl. [End of Program]

แสดงข้นั ตอนสำหรบั การแทรกโหนดในลิงค์ลสิ ต์คนู่ ัน้ ดงั ภาพประกอบท่ี 4.20

count Rear pHead F count Rear pHead B F
0 Nulll
B 5 1 Nulll 5 Nulll
Nulll

pNew pNew
w w

a) ก่อนแทรก b) หลังแทรก

ภาพประกอบที่ 4.20 การแทรกโหนดในลงิ ค์ลสิ ต์คู่

71

2) การลบโหนดในลงิ ค์ลสิ ตค์ ู่
ในการลบโหนดลิงค์ลสิ ตค์ มู่ ขี ัน้ ตอนเหมือนกับการลบโหนดในลงิ คเ์ ดย่ี ว สว่ นข้นั

ตอนการลบโหนดในลงิ คล์ สิ ต์คู่สามารถเขยี นขั้นตอนวิธไี ด้ดังน้ี
Pseudo Code 4.20: Algorithm deleteDbl (list,deleteNode)
This algorithm deletes a node from a double-linked list.
Pre list is metadata structure to a valid list.
deleteNode is a pointer to the node to be deleted.
Post node deleted.
Step 1 If (deleteNode null)
abort (“Impossible condition in delete double”).
Step 2 End If [End of If Structure]
Step 3 If (deleteNode back not null)
Point predecessor to successor.
Set predecessor to deleteNode back.
Set predecessor fore to deleteNode fore.
Step 4 else
Update head to deleteNode fore.
Set list head to deleteNode fore.
Step 5 End If
Step 6 If (deleteNode not null)
Point successor to predecessor.
Set successor to predecessor.
Set successor back to deleteNode back.
Step 7 else
Point rear to predecessor.
Set list rear to deleteNode back.
Step 8 End If. [End of IF Strucrture]
Step 9 recycle. (deleteNode)
Step 10 End deleteDbl. [End of Program]

72

แสดงข้ันตอนสำหรบั การลบโหนดในลิงคล์ ิสตค์ ู่ ดังภาพประกอบท่ี 4.21

count Rear pHead B F BF B F
5 15 10
3 Null Null
pPre pDlt
l

pSucc

a) กอ่ นลบ

count Rear pHead B F B F B F
3 Nulll 5 Recycled 10
Null

pPre pSucc

b) หลงั ลบ

ภาพประกอบที่ 4.21 การลบโหนดในลิงคล์ ิสต์คู่

4.5 สรุป
โครงสร้างข้อมูลลิงค์ลิสต์ เป็นโครงสร้างข้อมูลแบบเชิงเส้นที่มีลักษณะการเก็บของข้อมูลด้วย

โหนด (Node) ต่อเนื่องกัน โดยแต่ละโหนดจะถูกระบุตำแหน่งบนหน่วยความจำ (Address) เพื่อใช้
อา้ งอิงหรือการเข้าถึงได้ โหนดจะประกอบด้วย 2 ส่วนคอื ส่วนขอ้ มูลของลิงคล์ ิสต์ (Data) เป็นส่วนที่ใช้
จัดเก็บข้อมูลจะมีการเก็บสารสนเทศที่สามารถนำไปใช้ประโยชน์ เพื่อนำไปใช้ในการประมวลผลตามท่ี
ต้องการต่อไป และส่วนลิงค์ (Link) ที่จัดเก็บพอยน์เตอร์เป็นตัวแปรเก็บค่าอ้างอิงไปยังที่อยู่ของโหนด
ถดั ไป

ลิงค์ลิสต์สามารถแบ่งออกได้เป็น 3 ชนิด คือ 1) ลิงค์ลิสต์เด่ียว (Singly Linked List) ลักษณะ
ของลิงค์ลิสต์เด่ียวคือ ลิงค์ลิสต์ที่มีทิศทางเดียวโดยแต่ละโหนดจะเก็บพอยน์เตอร์เพียงตัวเดียวนั้นคือ
พอยน์เตอร์สำหรับช้ีตำแหน่งของโหนดถัดไป (Link) และโหนดสุดท้ายจะเก็บค่า Null เท่าน้ัน 2) ลิงค์
ลสิ ตค์ ู่ (Doubly Linked List) ลักษณะของลิงคล์ ิสต์ค่คู ือ ลงิ ค์ลสิ ตท์ ม่ี ี 2 ทิศทางโดยแตล่ ะโหนดเก็บ
พอยนเ์ ตอร์สองตัวสำหรับชตี้ ำแหนง่ ของโหนดถดั ไป (Forward Pointer: F) และตำแหน่งของโหนดที่อยู่
ก่อนหน้า (Backward Pointer : B) และ 3) ลิงค์ลิสต์วงกลม (Circular Linked List) ลักษณะของลิงค์
ลิสต์วงกลมคือ ลิงค์ลิสต์ที่มีการเช่ือมโยงเป็นวงกลม โดยพอยน์เตอร์ของโหนดสุดท้ายจะชี้ตำแหน่งของ
โหนดแรกของลงิ ค์ลสิ ต์เสมอ

73

การดำเนนิ งานพ้นื ฐานของลิงค์ลิสตป์ ระกอบด้วย การแทรก การลบ การอา่ น และการทอ่ งเข้า
ไปในลิสต์ เราสามารถพบลิงค์ลิสต์ได้ในชีวิตประจำวัน เช่น ลิงค์ลิสต์ของนักศึกษาที่ลงทะเบียนเรียน
ลิงค์ลิสต์ของรายการสินค้า ลิงค์ลิสต์ของพนักงานในบริษัท ลิงค์ลสิ ต์ของที่น่ังโรงภาพยนตร์ ในกรณีของ
โครงสร้างข้อมูลลิงค์ลิสต์ คือ ลำดับของสมาชิกที่มีขนาดจำกัด ถึงแม้ว่าการทำงานของลิสต์น้ันแตกตา่ งกัน
ไปตามลักษณะการประยกุ ต์ใช้งาน

74

คำถามทา้ ยบทที่ 4

1. อธิบายความหมายและยกตัวอย่างโครงสรา้ งข้อมูลลิงคล์ สิ ต์ตามความเขา้ ใจของนักศึกษา
2. ลิงค์ลิสตแ์ บ่งออกเป็นกป่ี ระเภท แตล่ ะประเภทแตกต่างกันอย่างไร
3. จงอธบิ ายขอ้ ดี และข้อเสียของโครงสรา้ งข้อมลู ลิงค์ลสิ ต์มาพอสงั เขป
4. โครงสร้างสว่ นหัว (Head Node) มีความสำคญั อย่างไร
5. จงเขียนกระบวนการทำงานของลงิ คล์ สิ ต์ต่อไปน้ีพรอ้ มวาดรูปประกอบ

5.1 จงเขียนกระบวนงานเพ่อื ทอ่ งไปในโครงสร้างข้อมลู ลิงค์ลสิ ต์ เพื่อใชเ้ กบ็ คะแนนสอบใน
โครงสร้างแถวลำดบั และคำนวณหาค่าเฉลี่ย

5.2 จงเขยี นกระบวนการ Delete สำหรบั การดำเนนิ การลบสมาชกิ ออกจากลิงค์ลสิ ต์
5.3 จงเขียนกระบวนการ Insert สำหรับการดำเนินการใสข่ อ้ มูลลงในลงิ คล์ สิ ต์
6. จงเขยี นกระบวนงานที่สามารถคน้ หาสมาชิกที่อยู่ในลงิ คล์ ิสต์แบบวงกลม
7. กำหนดลิงคล์ ิสต์แบบคทู่ ี่ประกอบดว้ ยตัวช้ี P1 และ P2 จงตอบคำถามข้อ (1) - (5)

P1 P2

Null D I R T Y Null

(1) แสดงขั้นตอนวธิ ใี นการเพ่ิมโหนดแรกของลงิ คล์ สิ ต์
(2) แสดงขนั้ ตอนวิธีการแทรกโหนดระหวา่ งโหนดใดๆ ในลงิ คล์ สิ ต์
(3) แสดงข้ันตอนวิธีการแทรกโหนดท้ายลงิ ค์ลิสต์
(4) แสดงขัน้ ตอนวธิ ีการลบโหนดท้ายลงิ ค์ลสิ ต์
(5) แสดงขนั้ ตอนวิธีการลบโหนดใดๆ ระหว่างโหนดสองโหนดในลงิ ค์ลิสต์

จงใชร้ ปู ต่อไปน้ีตอบคำถามข้อ 8 P1

P1

BEST

8. จากรูปท่กี ำหนดให้จงวาดรปู ของข้นั ตอนวิธีในข้อ 7
9. ฟงั ก์ชัน Recyele() มีหน้าที่ทำอะไร จงอธิบาย
10. จงสรุปคุณลักษณะท่ีสำคัญของลงิ คล์ ิสต์ค่แู ละลงิ คล์ ิสต์แบบวงกลม

บทท่ี 5
โครงสร้างข้อมลู แบบสแตก

สแตกเปน็ โครงสร้างขอ้ มูลแบบเชิงเสน้ ที่จัดเก็บข้อมลู ต่อเนอื่ งกนั เป็นแถว ทกุ คร้ังทมี่ ีการกระทำ
กับสมาชิกในสแตกได้แก่ การนำข้อมูลเข้าสู่สแตก และการนำข้อมูลออกจากสแตกสามารถทำได้ที่ด้าน
ปลายหรือด้านบนสุดเทา่ น้ัน ดังนน้ั อนั ดับของการนำสมาชกิ เขา้ และออกจากสแตกมีความสำคัญเน่ือง
จากสามาชกิ ใหม่ลา่ สุดท่เี ขา้ ไปในสแตกจะเป็นตวั ที่ต้องเอาออกจากสแตกก่อนตัวอื่นๆ เสมอ ซง่ึ หมายถงึ
สมาชิกท่ีเข้าไปในสแตกหลังสุดจะต้องกลับออกจากสแตกก่อนสมาชิกตัวอ่ืน จึงทำให้หลักการของ
โครงสร้างข้อมูลแบบสแตกมีลักษณะเป็น “เข้าหลังออกก่อน” โครงสร้างน้ีจึงถูกเรียกว่าเป็นโครงสร้าง
แบบ LIFO (Last-In , First-Out)

5.1 ความรพู้ ื้นฐานเกย่ี วกบั สแตก
สแตกเป็นโครงสร้างข้อมูลแบบเชิงเส้น (Linear List) ที่สามารถนำข้อมูลเข้าหรือออกได้ทาง

เดียวเท่านั้นคือ ตำแหน่งด้านบนของสแตก (Top Of Stack) โดยมีตัวดำเนินการคอยจัดการกับข้อมูล
ไดแ้ ก่ การนำข้อมูลเขา้ (Push) และ การนำขอ้ มลู ออก (Pop)

ตัวอย่างการทำงานแบบโครงสร้างข้อมูลแบบสแตกที่สามารถเห็นได้ในชีวิตประจำวันทั่วไป
ไดแ้ ก่ การวางจานซ้อนกันในกล่อง จานใบใหม่น้นั จำเปน็ ต้องวางไว้ด้านบนสุดเสมอ และหากต้องการนำ
จานออกมาใช้งานกต็ อ้ งเอาออกจากดา้ นบนสดุ ก่อน ดงั ภาพประกอบที่ 5.1

(a) การวางจานซ้อนในกล่อง (b) การนำจานออกจากกล่องมาใช้
งาน

ภาพประกอบที่ 5.1 การทำงานของโครงสรา้ งข้อมูลแบบสแตก

การนำสแตกไปใชง้ านน้นั ไม่ว่าจะเปน็ โครงสร้างสแตกแบบแถวลำดบั (Array) หรอื โครงสรา้ ง
สแตกแบบลิงค์ลิสต์ (Linked List) จะมีตัวแปรตัวหนงึ่ ท่ีใช้เป็นตัวช้ีสแตก (Stack Pointer :SP) เพ่ือเป็น
ดชั นีของข้อมูลที่อยู่ตำแหน่งบนสุดของสแตก (Top of Stack : TS) ซ่ึงจะทำให้สามารถจัดการข้อมูลท่ี
จะเกบ็ ในสแตกไดง้ ่าย ดงั นน้ั โครงสร้างขอ้ มลู แบบสแตกจะแบ่งออกเป็น 2 ส่วนที่สำคัญ คอื

76

1. ตวั ช้ีสแตก (Stack Pointer: SP) เป็นดัชนีของขอ้ มูลทอ่ี ยูต่ ำแหน่งบนสุดของสแตก
2. สมาชกิ ของสแตก (Stack Element) เป็นขอ้ มลู ที่จะเก็บลงไปในสแตกซ่ึงจะต้องเป็นขอ้ มลู
ชนดิ เดยี วกนั
สแตกจะต้องมีการกำหนดขนาดของสแตกท่ีสามารถเก็บจำนวนข้อมูลสูงสุดในสแตกได้ (Max)
เพอื่ ใชต้ รวจสอบการนำขอ้ มูลเขา้ หรือการนำข้อมูลออก

5.2 การจัดการกบั ข้อมูลในสแตก
ในการทำงานของสแตกประกอบดว้ ย 2 กระบวนการคือ การนำข้อมูลเข้าในสแตก (Push) และ

การนำข้อมลู ออกจากสแตก (Pop)
1. การนำข้อมูลเข้าในสแตก (Push) จะกระทำท่ีดา้ นบนของสแตก โดยตอ้ งมีการตรวจสอบ

เน้ือที่ในสแตกก่อนว่ามีท่ีเหลือว่างให้เก็บข้อมูลได้อีกหรือไม่ โดยหากมีเน้ือที่ว่างในสแตก สามารถนำ
ขอ้ มลู เข้าทต่ี ำแหนง่ บนสุดของสแตก และสามารถนำขอ้ มลู เข้าในสแตกไดเ้ รื่อยๆ จนกวา่ สแตกจะเต็ม
(สแตกจะเต็มก็ต่อเมื่อTop = Max ) เช่นถ้าสแตกนั้นจองเน้ือท่ีไว้ N เน้ือที่ หมายถึงสามารถบรรจุ
สมาชิกในสแตกได้ N ตัว หากเป็นสแตกว่าง ค่าของ Top จะเป็นศูนย์ เขียนแทนด้วย Top = 0 หรือ
Top = Null แต่หากสแตกเต็ม(คา่ Top = Max)จะไม่สามารถนำขอ้ มูลเข้าในสแตกได้อีกดังภาพประกอบ
ท่ี 5.2 เมอ่ื ต้องการนำขอ้ มูล 5, 3, 6 เข้าไปสแตกตามลำดบั

Max = 6 Max =6 Max = 6 Max = 6
Top = 3 Top = 4 Top = 5 Top = 6

top 6

top 3 push(6) 3

Top 5 push(3) 5 5

Top 9 push(5) 9 99

7 7 77

2 2 22

ภาพประกอบท่ี 5.2 การนำข้อมลู เข้าในสแตก
จากภาพประกอบที่ 5.2 สแตกมขี นาด 6 (Max = 6) มีขอ้ มูลท่เี กบ็ ในสแตกคือ 2, 7, 9 ดชั นี
ของข้อมูลทอี่ ย่ตู ำแหน่งบนสุดของสแตกเท่ากับ 3 (Top = 3) เม่ือมกี ารนำขอ้ มูล 5 เข้ามาในสแตก ค่า
Top จะเพิ่มขน้ึ อีก 1 (Top = Top + 1) แล้วนำข้อมลู 5 มาเกบ็ ไว้ทีต่ ำแหนง่ ที่ Top ช้ีอยู่ เมือ่ มีการนำ
ข้อมูล 3 เข้ามาในสแตก คา่ Top จะเพ่มิ ข้ึนอีก 1 (Top = Top + 1) แลว้ นำข้อมูล 3 มาเก็บไวท้ ี่
ตำแหน่งท่ี Top ชอ้ี ยู่ และเมื่อมกี ารนำข้อมูล 6 เข้ามาในสแตก ค่า Top จะเพม่ิ ข้ึนอีก1(Top=Top + 1)
แล้วนำข้อมลู 6 มาเก็บไว้ทต่ี ำแหน่งที่ Top ชี้อยู่ ดงั นั้นสามารถนิยามขั้นตอนการนำข้อมูลเขา้ ใน
สแตกดังนี้

77

นิยาม Push (S,x)
ถา้ ให้ S เป็นสแตก และ x เป็นขอ้ มูลท่ีต้องการนำเขา้ สู่สแตก หรอื นำออกจากสแตก
กระบวนการ Push (S, x) หมายถึง การนำข้อมูล x ลงสแตก โดยการ Push จะเร่ิมจากสแตกว่าง ให้
ค่าท๊อปมีค่าเป็นศูนย์ (Top = 0) เมื่อมีการ Push ข้อมูลเข้าในสแตก ค่าของท๊อปจะเปล่ียนเพิ่มขึ้นทีละ
หนึ่งทกุ ครง้ั ทท่ี ำการ Push โดยกำหนดให้ Max คือขนาดของสแตก
ข้ันตอนการนำข้อมูลเข้าในสแตก จะเริ่มจากการตรวจสอบท่ีว่างในสแตกก่อน
ถ้าไมม่ ีท่ีว่าง จะใชเ้ งอ่ื นไขสแตกเต็ม (Overflow) ดงั นั้นสามารถเขยี นข้ันตอนวิธีการการนำข้อมลู เข้าใน
สแตกไดด้ ังน้ี
Pseudo Code 5.1 : Procedure PUSH(S,Top,Max,X)
This procedure pushes an item into a stack.
Step 1 [Stack already filled?]

If Top = Max then Print “StacK Overflow” and Return.
Step 2 Set Top = Top+1. [Increases Top by 1.]
Step 3 Set S[Top] = X. [ Insert X in new Top position.]
Step 4 Return.

2. การนำข้อมลู ออก (Pop) หมายถึงการเอาข้อมูลทอี่ ยู่บนสุดในสแตกหรอื ท่ีชี้ด้วยทอ๊ ป

ออกจากสแตกเรียกว่าการ Pop ในการ Pop น้ันจะสามารถ Pop ข้อมูลจากสแตกได้เรื่อยๆ จนกว่า

ข้อมูลจะหมดสแตก หรือเป็นสแตกว่าง (Top = 0) โดยก่อนที่จะนำข้อมูลออกจากสแตก จะต้องมีการ

ตรวจสอบวา่ ในสแตกมขี อ้ มลู เก็บอยหู่ รือไม่ ดงั ภาพประกอบท่ี 5.3

pop 6 , 3 , 5 , 9 , 7 ออก ตามลำดับ

Max=6 Max=6 Max=6 Max=6
Top =6 Top =3 Top =2 Top =1

6

3

5 Pop(6,3,5) Pop(9) pop(7)

9 Top 9

7 7 top 7

2 2 2 top 2

ภาพประกอบท่ี 5.3 การเอาข้อมลู ออกจากสแตก

78

จากภาพประกอบท่ี 5.3 มีข้อมูลที่เก็บในสแตกทั้งหมด 6 ค่า โดยท่ี ค่า Top ของสแตกมีค่า
เทา่ กบั 6 เม่ือมีการนำข้อมลู ออกโดยนำข้อมลู ที่อยบู่ นสดุ ออกก่อน คา่ แรกคือ 6 เมอ่ื นำ 6 ออก จะมีการ
ลดคา่ Top (Top = Top – 1) โดย Top จะช้ีท่ีตำแหน่งข้อมูล 3 ซ่งึ ถอื ว่า 3 เปน็ ขอ้ มลู บนสดุ ในรอบนี้
เม่อื มีการนำข้อมลู 3 ออก จะมกี ารลดค่า Top (Top = Top -1) โดย Top จะชีต้ ำแหนง่ ข้อมูล 5 ซึง่ ถอื
วา่ 5 เป็นข้อมูลบนสดุ ในรอบนี้ เมื่อมีการนำข้อมูล 5 ออก จะมีการลดค่า Top (Top = Top -1) โดย
Top จะช้ีตำแหนง่ ข้อมลู 9 ซ่ึงถือวา่ 9 เป็นข้อมลู บนสุดในรอบนี้ เมื่อมกี ารนำขอ้ มูล 9 ออก จะมกี ารลด
ค่า Top (Top = Top -1) โดย Top จะช้ีตำแหน่งข้อมลู 7 ซ่ึงถือวา่ 7 เป็นข้อมูลบนสดุ ในรอบน้ี เม่อื มี
การนำข้อมลู 7 ออก จะมีการลดค่า Top (Top = Top -1) โดย Top จะช้ีตำแหน่งข้อมูล 2 ซึ่งถอื วา่ 2
เป็นขอ้ มูลบนสุดในรอบน้ี ดงั น้ันสามารถนิยามข้ันตอนการนำขอ้ มลู ออกจากสแตกไดด้ งั น้ี

นิยาม Pop(S)
ถ้าให้ S เป็นสแตก การ Pop(S) คือ การนำข้อมูลบนสุดในสแตกออกจากสแตก และ
ให้ค่าเป็นข้อมูลท่ีนำออกจากสแตก ดังนั้น คำส่ัง X = Pop(S) ก็คือการนำข้อมูลท่ีท๊อปของ สแตก
ออกมา และใสค่ ่าไวท้ ี่ X หรอื การเซตค่า X ให้เทา่ กบั ขอ้ มลู ท่ีนำออกจากสแตก
ขัน้ ตอนการนำข้อมลู ออกจากสแตกจะเริ่มจากการตรวจสอบวา่ มีสมาชิกที่ต้องการลบ
ออกจากสแตกหรือไม่ หากไม่มีจะใช้เงอื่ นไขสแตกวา่ ง (Underflow) ดังน้ันสามารถเขยี นขน้ั ตอนวธิ ีการ
นำข้อมูลออกจากสแตกได้ดงั น้ี
Pseudo Code 5.2 : Procedure Pop(S,Top, x)
This procedure deletes the top element of Stack and assigns it to the
variable x.
Step 1 [Stack has an item to be removed?]

If Top = 0 then Print “Stack Underflow” and Return.
Step 2 Set x = S[Top]. [Assigns Top element to x.]
Step 3 Set Top = Top – 1. [Decreases Top by 1.]
Step 4 Return.

5.3 ปัญหาทเ่ี กดิ ข้ึนกับสแตก
ปญั หาท่เี กดิ ขนึ้ กบั สแตกคือ ข้อผดิ พลาดทเ่ี กิดข้ึนซงึ่ มีผลมาจากการจดั การสแตกมดี งั นี้
กรณีที่ 1 สแตกเต็ม (Full Stack)
กรณีที่ 2 สแตกวา่ ง (Empty Stack)
กรณีที่ 1 สแตกเตม็ (Full Stack)
การนำข้อมูลเข้าในสแตกทุกคร้ังจะมกี ารตรวจสอบทวี่ ่างในสแตกว่ามีท่ีว่างเหลือหรอื ไม่ ถา้ ไม่มี

ที่ว่างเหลืออยู่ ก็จะไม่สามารถทำการเพ่ิมข้อมูลในสแตกได้ ในกรณีเช่นนี้ เรียกว่าเกิด สแตกล้น (Stack

79

Overflow) โดยการตรวจสอบว่าสแตกเต็มหรือไม่จะใช้ตัวชี้สแตก (Stack pointer) มาเปรียบเทียบกับ
ค่าสูงสุดของสแตก (Max) หากตัวชี้สแตกมีค่าเท่ากับค่าสูงสุดของสแตกแล้วแสดงว่าไม่มีท่ีว่างให้ข้อเก็บ
ข้อมูลอกี

ภาพประกอบท่ี 5.4 สแตกเต็ม (Full Stack)

กรณีท่ี 2 สแตกวา่ ง (Empty Stack)
นิยาม empty(S) ถ้า S เป็นสแตก ขบวนการ empty(S) จะส่งผลเป็นจริง (true) เมอ่ื สแตก
ว่าง และสง่ ผลเปน็ เท็จ (false) เมือ่ สแตกไมว่ ่างหรอื สแตกเต็ม
การนำข้อมูลออกจากสแตกทุกครั้งจะมีการตรวจสอบข้อมูลในสแตกว่ามีข้อมูลในสแตกหรือไม่
ถ้าไม่มีข้อมูลในสแตกเหลืออยู่ ก็ไม่สามารถทำการนำข้อมูลออกได้ ในกรณีเช่นน้ีเรียกว่าเกิดสถานะ
สแตกจม (Stack Underflow) โดยการตรวจสอบว่าสแตกวา่ งหรอื ไม่ จะตรวจสอบตัวช้ีสแตกว่าเทา่ กับ
0 หรอื Null หรือไม่ ถ้าเท่ากับ 0 แสดงว่า สแตกว่าง จงึ ไม่สามารถนำข้อมูลออกจากสแตกได้

ภาพประกอบท่ี 5.5 สแตกว่าง (Empty Stack)

5.4 สแตกกับการประยุกต์ใช้งาน
ดว้ ยคณุ สมบัติของสแตกท่มี ีหลักการทำงานในรูปแบบ LIFO จึงสามารถนำสแตกไปประยุกต์ใช้

งานได้หลากหลาย เช่น การเรียงลำดับข้อมูลแบบย้อนกลับ (Reversing Data) การแตกข้อมูลออกเป็น
ส่วนๆ (Parsing) การหน่วงเวลา (Postponement) เพ่ือรอการประมวลผลในช่วงจังหวะที่เหมาะสม
ดังน้ันสแตกจึงมีประโยชน์มากมายต่อการนำไปประยุกต์ใช้งาน โดยเฉพาะการประมวลผลนิพจน์ทาง
คณติ ศาสตรบ์ นเครื่องคอมพิวเตอร์

การใช้สแตกเพอ่ื แปลงรปู นิพจนท์ างคณติ ศาสตร์
นิพจน์ทางคณิตศาสตร์ (Arithmetic Expression) คือ การนำค่าคงที่และตัวแปรถือเป็นตัวถูก
ดำเนินการ (Operand) มาเช่ือมกนั ด้วยเครื่องหมายทางคณิตศาสตร์ (Operator) ถือเป็นตัวดำเนินการ

80

ซึ่งได้แก่ เครื่องหมายยกกำลัง (^) , คูณ (*) , หาร (/) ,บวก (+) , ลบ (-) ดังนั้น รูปแบบนิพจน์ทาง

คณิตศาสตร์ มี 3 รปู แบบไดแ้ ก่

1. นพิ จน์ Infix คอื นิพจน์ทตี่ วั ดำเนินการอย่รู ะหว่างตวั ถกู ดำเนนิ การ เชน่ A+B-C

2. นิพจน์ Prefix คือ นิพจน์ตวั ดำเนนิ การอยู่หนา้ ตัวถูกดำเนินการ เช่น +-AB

3. นิพจน์ Postfix คือ นพิ จน์ทตี่ วั ดำเนนิ การอยู่หลังตัวถูกดำเนินการ เชน่ AC*+

ลำดบั การทำงานของตวั ดำเนนิ การในนพิ จน์ทางคณิตศาสตร์ นั้นไดม้ ีการลำดบั ความสำคญั ของ

ตวั ดำเนนิ การจากลำดับสำคัญมากสดุ ไปน้อยสดุ ตามลำดบั ดังนี้

1. หากมวี งเลบ็ ( ) ให้ทำในวงเลบ็ กอ่ น

2. เคร่ืองหมายยกกำลัง ( ^ )

3. เครอื่ งหมายคูณ ( * ) , หาร ( / )

4. เคร่อื งหมายบวก ( + ) , ลบ ( - )

ตัวอยา่ งท่ี 5.1 นพิ จน์ทางคณิตศาสตร์และลำดบั การคำนวณ

A-B*C (A + B) * C

11

22

(A – B) * (C / D) A* B / (C / D)
12 1
3
2
3

ขัน้ ตอนวิธีการแปลงนพิ จน์ Infix เป็น นพิ จน์ Postfix
สามารถแปลงนิพจน์ Infix ให้เป็น Postfix ได้โดยอาศัยสแตกที่มีคุณสมบัติการเข้าหลังออก
กอ่ นหรอื LIFO โดยมีขนั้ ตอนวธิ ีในการแปลงนิพจน์ ดังน้ี

1. ถ้าข้อมูลเข้า (Input) เป็นตัวถูกดำเนินการ (Operand) ให้นำออกไปเป็นผลลัพธ์
(Output)

2. ถา้ ขอ้ มูลเขา้ เปน็ ตวั ดำเนินการ (Operator) ให้ดำเนินการ ดงั นี้
2.1 ถา้ สแตกวา่ ง ให้ Push ตวั ดำเนนิ การลงในสแตก
2.2 ถ้าสแตกไม่ว่าง ให้เปรียบเทียบ ตัวดำเนินการท่ีเข้ามากับตัวดำเนินการที่

อยูใ่ นตำแหนง่ TOP ของสแตก
2.2.1 ถ้าตัวดำเนินการท่ีเข้ามามีความสำคัญมากกว่าตัวดำเนินการท่ี

ตำแหนง่ TOP ของสแตกให้ Push ตัวดำเนินการลงสแตก

81

2.2.2 ถ้าตัวดำเนินการท่ีเข้ามามีความสำคัญน้อยกว่าหรือเท่ากับ ตัว
ดำเนนิ การที่อยู่ในตำแหน่ง TOP ของสแตก ให้ Pop ค่าบนสุดของสแตกออกไปเป็นผลลัพธ์ แล้วทำการ
เปรียบเทียบตัวดำเนินการ ที่เข้ามากับ ตัวดำเนินการ ที่ตำแหน่ง TOP ต่อไป จะหยุดจนกว่า ตัว
ดำเนินการท่เี ขา้ มาจะมี ความสำคญั มากกว่า ตัวดำเนินการทีต่ ำแหนง่ TOP ของสแตก แล้วจึง Push ตัว
ดำเนนิ การท่เี ข้ามานั้นลงสแตก

3. ถ้าขอ้ มูลเขา้ เป็นวงเลบ็ เปดิ ให้ Push ลงสแตก และถือวา่ หลังวงเลบ็ เปดิ สแตกวา่ ง
4. ถา้ ข้อมูลเขา้ เป็นวงเลบ็ ปดิ ให้ Pop ข้อมลู ออกจากสแตกไปเป็นผลลพั ธ์จนกว่าจะถึง
วงเลบ็ เปิด จากนน้ั ทง้ิ วงเล็บเปดิ และปดิ ไป
5. ถ้าไม่มีข้อมูลเข้าแต่ยังมีข้อมูลค้างอยู่ในสแตก ให้ Pop ข้อมูลท่ีค้างอยู่ในสแตก
ออกไปเป็นผลลพั ธจ์ นกวา่ สแตกจะวา่ ง

ตัวอยา่ งที่ 5.2 การแปลงนิพจน์ Infix เป็นนพิ จน์ Postfix

นพิ จน์ (A * B) + (C / D)

นิพจน์ Infix Stack นพิ จน์ Postfix

ขอ้ มูลเข้า ( Input) เก็บตวั ดำเนนิ การ ขอ้ มูลออก (Output)

( ( วา่ ง

A (A

* (* A

B (* AB

) ว่าง AB*

+ + AB*

( +( AB*

C +( AB*C

/ +(/ AB*C

D +(/ AB*CD

) + AB*CD/

วา่ ง วา่ ง AB*CD/+

82

นิพจน์ A + B * C Stack นพิ จน์ Postfix
นิพจน์ Infix เกบ็ ตวั ดำเนนิ การ ขอ้ มูลออก (Output)
A
ข้อมูลเข้า ( Input) ว่าง A
A + AB
+ + AB
B +* ABC
* +* ABC*+
C วา่ ง
วา่ ง

นิพจน์ A / B + (C – D) Stack นพิ จน์ Postfix
นิพจน์ Infix เก็บตวั ดำเนนิ การ ข้อมลู ออก (Output)
A
ข้อมลู เขา้ ( Input) ว่าง A
A / AB
/ / AB/
B + AB/
+ +( AB/C
( +( AB/C
C +(- AB/CD
- +(- AB/CD-
D + AB/CD-+
) ว่าง
ว่าง

83

นิพจน์ (A + B) * (C ^ D – E) * F

นิพจน์ Infix Stack นิพจน์ Postfix
ข้อมูลออก (Output)
ขอ้ มลู เข้า ( Input) เกบ็ ตัวดำเนนิ การ ว่าง
A
(( A
AB
A( AB+
AB+
+ (+ AB+
AB+C
B (+ AB+C
AB+CD
) ว่าง AB+CD^
AB+CD^E
** AB+CD^E-
AB+CD^E-*
( *( AB+CD^E-*F
AB+CD^E-*F*
C *(

^ *(^

D *(^

- *(-

E *(-

)*

**

F*

ว่าง วา่ ง

ขนั้ ตอนวิธีการแปลงนพิ จน์ Infix เปน็ นิพจน์ Prefix
สามารถแปลงนิพจน์ Infix ให้เป็น Prefix ได้โดยอาศัยสแตกท่ีมีคุณสมบัติการเข้าหลังออกก่อน
หรือ LIFO โดยอ่านข้อมูลนำเข้าจากนิพจน์ Infix จากหลังสุดไปหน้าสุดตามลำดับ ขั้นตอนวิธีในการ
แปลงนพิ จน์ ดังน้ี

1. ถ้าข้อมูลเข้า (Input) เป็นตัวถูกดำเนินการ (Operand) ให้นำออกไปเป็นผลลัพธ์
(Output)

2. ถา้ ข้อมูลเข้าเป็นตัวดำเนนิ การ (Operator) ใหด้ ำเนินการ ดงั น้ี
2..1 ถ้าสแตกวา่ ง ให้ Push ตวั ดำเนินการลงในสแตก
2..2 ถ้าสแตกไม่วา่ ง ให้เปรยี บเทยี บ ตัวดำเนินการท่ีเข้ามากับตัวดำเนินการที่

อย่ใู นตำแหนง่ TOP ของสแตก
2.2.1 ถ้าตัวดำเนินการที่เข้ามามีความสำคัญมากกว่าหรือเท่ากับตัว

ดำเนินการที่ตำแหน่ง TOP ของสแตกให้ Push ตวั ดำเนินการลงสแตก

84

2.2.2 ถ้าตัวดำเนินการท่ีเข้ามามีความสำคัญน้อยกว่า ตัวดำเนินการ
ที่อยู่ในตำแหน่ง TOP ของสแตก ให้ Pop ค่าบนสุดของสแตกออกไปเป็นผลลัพธ์ แล้วทำการ
เปรียบเทียบตัวดำเนินการ ที่เข้ามากับ ตัวดำเนินการ ท่ีตำแหน่ง TOP ต่อไป จะหยุดจนกว่า ตัว
ดำเนินการท่ีเข้ามาจะมี ความสำคัญมากกว่าหรือเท่ากับ ตัวดำเนินการท่ีตำแหน่ง TOP ของสแตก แล้ว
จงึ Push ตวั ดำเนนิ การที่เข้ามานนั้ ลงสแตก

3. ถ้าข้อมูลเขา้ เปน็ วงเล็บเปดิ ให้ Push ลงสแตก และถือว่าหลงั วงเล็บเปดิ สแตกวา่ ง
4.. ถ้าข้อมูลเข้าเป็นวงเล็บปิด ให้ Pop ข้อมูลออกจากสแตกไปเป็นผลลัพธ์จนกว่าจะ
ถงึ วงเล็บ เปิด จากน้ันท้งิ วงเล็บเปิดและปิดไป
5. ถ้าไม่มีข้อมูลเข้า แต่ยังมีข้อมูลค้างอยู่ในสแตก ให้ Pop ข้อมูลท่ีค้างอยู่ในสแตก
ออกไปเปน็ ผลลพั ธจ์ นกว่าสแตกจะวา่ ง

ตัวอยา่ งที่ 5.3 การแปลงนิพจน์ Infix เป็นนพิ จน์ Prefix

นิพจน์ (A * B) + (C / D)

นพิ จน์ Infix Stack นพิ จน์ Prefix
ขอ้ มูลออก (Output)
ขอ้ มลู เขา้ ( Input) เก็บตวั ดำเนนิ การ
ว่าง
(( D
D
D( CD

/ (/ /CD
/CD
C (/ /CD
B/CD
) วา่ ง B/CD
AB/CD
++ *AB/CD
+*AB/CD
) +(

B +(

* +(*

A +(*

)+

วา่ ง วา่ ง

85

นิพจน์ A + B * C Stack นิพจน์ Prefix
นพิ จน์ Infix เกบ็ ตวั ดำเนินการ ขอ้ มูลออก (Output)

ข้อมูลเขา้ ( Input) วา่ ง C
C * C
* * BC
B + *BC
+ + A*BC
A ว่าง +A*BC
วา่ ง

นิพจน์ A / B + (C – D) Stack นพิ จน์ Postfix
นพิ จน์ Infix เก็บตัวดำเนนิ การ ขอ้ มลู ออก (Output)

ขอ้ มลู เข้า ( Input) ) วา่ ง
) ) D
D )- D
- )- CD
C วา่ ง
( + -CD
+ + -CD
B +/ B-CD
/ +/ B-CD
A วา่ ง AB-CD
ว่าง +/AB-CD

ขนั้ ตอนวิธกี ารแปลงนพิ จน์ Postfix เปน็ นิพจน์ Infix โดยใช้หลักการสแตก
1. ถ้าข้อมลู เขา้ เป็นตวั ถูกดำเนินการ (Operand) ให้ Push ลงสแตก
2. ถ้าข้อมูลเข้าเป็นตัวดำเนินการ (Operator) ให้ Pop สแตกสองคร้ัง แล้วนำตัว
ดำเนินการ (Operator) มาไว้ระหว่างตัวถูกดำเนินการ เพ่ือสร้างนิพจน์ Infix หลังจาก
นน้ั นำนิพจน์ Infix ทีไ่ ด้ push ลงสแตกอีกครง้ั
3. ทำขอ้ 1 และ 2 จนหมดหมดขอ้ มูลเขา้

86

ตัวอย่างที่ 5.4 การแปลงนิพจน์ Postfix เป็น นิพจน์ Infix โดยใช้หลักการสแตก แสดงการ
ประมวลผล ABC*+D- ซึ่งเป็น Postfix ของนิพจน์ A+B*C-D

*+ -
Pop, D
Pop, C Pop ,B*C Pop, A+B*C
D Push, A+B*C-D
C Pop, B Pop, A A+B*C A+B*C-D

B B Push, B*C B*C Push, A+B*C

AA A A A+B*C

ภาพประกอบท่ี 5.6 แสดงขั้นตอนการแปลงนพิ จน์ Postfix เป็น นพิ จน์ Infix

ขนั้ ตอนวิธกี ารแปลงนิพจน์ Postfix เป็น นพิ จน์ Prefix โดยใช้สแตก
1. ถ้าข้อมลู เขา้ เป็นตัวถกู ดำเนินการ (Operand) ให้ Push ลงสแตก
2. ถ้าข้อมูลเข้าเป็นตัวดำเนินการ (Operator) ให้ Pop ตัวถูกดำเนินการ (Operand)
ในสแตกสองคร้ัง แล้วนำตัวดำเนินการ (Operator) มาไว้ข้างหน้าเพื่อสร้างนิพจน์
Prefix หลังจากน้ันนำนพิ จน์ Prefix ทีไ่ ด้ push ลงสแตกอกี ครั้ง
3. ทำข้อ 1 และ 2 จนหมดขอ้ มูลนำเขา้

ตัวอย่างท่ี 5.5 การแปลงนิพจน์ Postfix เป็น นิพจน์ Prefix โดยใช้สแตก แสดงการ
ประมวลผลนพิ จน์ AB*CD/+ ใหเ้ ป็นนพิ จน์ +*AB/CD

* /+

Pop, B Pop, D Pop, /CD

Pop, A D Pop, C Pop, *AB

B Push , *AB C C Push, /CD /CD Push, +*AB/CD

AA *AB *AB *AB *AB +*AB/CD

ภาพประกอบท่ี 5.7 แสดงขัน้ ตอนการแปลงนิพจน์ Postfix เปน็ นพิ จน์ Prefix

87

ตัวอยา่ งงานที่นิยมใช้กับโครงสรา้ งข้อมลู แบบสแตก
1. การเรียงลำดบั ข้อมูลแบบยอ้ นกลบั (Reversing Data) ในการนำสแตกมาประยกุ ต์ใช้ที่
สามารถเข้าใจได้ง่ายก็คือ การเรียงลำดับข้อมูลแบบย้อนกลับ (Reversing Data) น้ันคือ เมื่อมีการเก็บ
ข้อมูลอย่างเรียงลำดับ หากมีการกลับตำแหน่งของข้อมูลแรกและข้อมูลสุดท้ายจะเปล่ียนไปอย่างมี
ความสัมพันธ์ เช่น ข้อมูล (2,4,6,8) จะกลายเป็น (8,6,4,2) ซึ่งสามารถเขียนขั้นตอนการทำงานได้ดังต่อ
นี้
Pseudo Code 5.3 : Program reverseNumber (เมื่อมีการใส่ข้อมูลท่ีเป็นตัวเลขทาง
แป้นพมิ พแ์ ละใส่ตัวเลขใสใ่ นสแตกท่ีละตวั และจะหยบิ ตัวเลขออกจากสแตกทล่ี ะตัว)
Step 1 stack = createStack.
Step 2 prompt (enter a number).
Step 3 read (numberfill stack).
Step 4 loop (not end of data and stack not full)

a. pushStack (number).
b. Promt (enter next number :<EOF> to stop).
c. Read(number).
Number in reverse .
Step 5 loop (not emptyStack(stack).
a. popStack (stack, dataOut).
b. print (dataOut).
Step 6 stack = destroyStack (stack).
Step 7 End reverseNumber.

2. การแปลงเลขฐานสอง ซ่งึ มาจากแนวความคดิ ของการกลับตวั เลขเรียงลำดับเชน่ กนั ซง่ึ
สามารถเขียนขนั้ ตอนวธิ ีได้ดงั นี้

Pseudo Code 5.4 : Program decimalToBinary (ให้มีการรับตัวเลขจากแป้นพิมพ์ และ
พมิ พเ์ ปน็ เลขฐาน 2 ซ่ึงจะใช้สแตกกลบั ตวั เลขผลลัพธท์ ่ไี ด้)

Step 1 Stack = createStack.
Step 2 prompt (enter a decimal to convert to binary).
Step 3 read (number).
Step 4 loop (number > 0)

digit =number modulo 2.
pushOK = push (stack,digit).

88

if (pushOK= false)
print (Stack overflow creating digit).
quit .

number = number /2.
Binary number created in stack.
Step 5 Loop (not emptyStack(stack))

poStack (stack, digit).
print (digt).
Destroy stack and return.
Step 6 destroy (stack).
Step 7 End decimalToBinary.

5.5 สรปุ
โครงสร้างข้อมูลของสแตกเป็นโครงสร้างท่ีมีเพิ่มและลบข้อมูลท้ังหมดกระทำท่ีปลาย

ข้างเดียวของของรายการแทนทส่ี แตกซึ่งเรียกวา่ ตำแหนง่ บนสดุ ของสแตก (Top of Stack) ซึ่งหากจะ
เปรียบเทียบสแตกกับสิ่งของในชีวิตประจำวัน เหมือนกับถาดอาหารท่ีวางซ้อนกันในห้างสรรพสินค้า
ทเ่ี มอ่ื ลูกคา้ มาใชบ้ ริการอาหารในศูนยอ์ าหาร ลกู ค้าจะหยิบถาดท่อี ยู่บนสดุ ของถาดท่ีวางซ้อนกนั

การนำข้อมูลเข้าในสแตก (Push) จะกระทำท่ีด้านบนของสแตก โดยต้องมีการตรวจสอบเน้ือท่ี
ในสแตกกอ่ นว่ามีท่ีเหลือว่างให้เก็บขอ้ มูลได้อีกหรอื ไม่ โดยหากมเี นื้อท่ีว่างในสแตก สามารถนำข้อมลู เข้า
ที่ตำแหน่งบนสุดของสแตก และสามารถนำข้อมูลเข้าในสแตกไดเ้ รอ่ื ยๆ จนกวา่ สแตกจะเต็ม แต่หาก
สแตกเต็มจะไม่สามารถนำข้อมูลเข้าในสแตกได้อีก ในการนำข้อมูลเข้าในสแตกทุกคร้งั จะมกี ารตรวจสอบ
ที่ว่างในสแตกว่ามีท่ีว่างเหลือหรือไม่ ถ้าไม่มีท่ีว่างเหลืออยู่ ก็จะไม่สามารถทำการเพิ่มข้อมูลในสแตกได้
ในกรณีเช่นน้ีเรยี กว่าเกดิ สแตกลน้ (Stack Overflow)

การนำขอ้ มลู ออก (Pop) การเอาขอ้ มูลท่อี ยู่บนสุดในสแตก หรอื ทช่ี ีด้ ้วยท๊อปออกจากสแตกใน
การ Pop น้ันจะสามารถ Pop ข้อมูลจากสแตกได้เร่ือยๆ จนกว่าข้อมูลจะหมดสแตกหรือเป็นสแตกว่าง
โดยก่อนท่ีจะนำข้อมูลออกจากสแตกจะต้องมีการตรวจสอบว่าในสแตกมีข้อมูลเก็บอยู่หรือไม่ในการนำ
ข้อมูลออกจากสแตกทุกคร้ังจะมีการตรวจสอบข้อมูลในสแตกว่ามีข้อมูลในสแตกหรือไม่ ถ้าไม่มีข้อมูล
ในสแตกเหลืออยู่ก็ไม่สามารถทำการนำข้อมูลออกได้ ในกรณีเช่นน้ีเรียกว่าเกิดสถานะ สแตกจม (Stack
Underflow)

ส่วนการประยกุ ตใ์ ช้โครงสรา้ งขอ้ มูลแบบสแตกการประยกุ ต์ใช้ โครงสร้างขอ้ มูลแบบสแตกท่ี
สำคญั คือ การหาผลลพั ธน์ พิ จน์ทางคณติ ศาสตร์ นอกจากนี้การประยกุ ตใ์ ช้สแตกสำหรบั โปรแกรมย่อย
เม่อื คอมพวิ เตอร์ถูกเรยี กโปรแกรมย่อยมาทำงาน ระบบจะต้องมกี ารจำตำแหนง่ ที่มีการเรยี กเกดิ ขนึ้ เพ่อื

89

ให้สามารถกลับมายังทเี่ ดิมได้ภายหลงั โปรแกรมยอ่ ยทำงานเสร็จแลว้ ดงั น้ันโปรแกรมหลักซงึ่ เป็นจุดเรม่ิ
ต้นของการทำงานจะทำงานเสรจ็ เป็นลำดบั สดุ ท้าย และโปรแกรมย่อยที่ถกู เรียกลำดับสุดทา้ ยก็จะถูก
ทำงานเสรจ็ ลำดับแรกและกลบั ไปยังโปรแกรมหลกั ท่ีเรียกใช้งาน นั่นคอื จะเห็นว่าลำดับของการทำงาน
ของโปรแกรมยอ่ ยจะดำเนินการไปในลักษณะ เข้าหลังออกก่อนเชน่ กัน

90

คำถามท้ายบทท่ี 5

1. จงอธิบายความหมายของสแตก และยกตัวอยา่ งประกอบเพ่ือให้เห็นภาพ และการจดั การกบั ข้อมลู

ในสแตกมวี ธิ ใี ดบ้าง

2. การเกิดสถานะ “Overflow” ของสแตกเกดิ ข้ึนไดด้ ้วยสาเหตใุ ดบ้างจงอธบิ าย สามารถตรวจสอบ

ไดอ้ ย่างไร

3. การเกดิ สถานะ “Underflow” ของสแตกเกิดขน้ึ ไดด้ ้วยสาเหตุใดบ้างจงอธิบาย สามารถตรวจ

สอบได้อยา่ งไร

4. สามารถนำสแตกไปประยุกต์ใช้กับงานด้านใดได้บ้าง

5. จงบอกข้อจำกัดของโครงสรา้ งขอ้ มลู แบบสแตก

6. จงเขยี นลำดับความสำคัญในการทำงานของตวั ดำเนนิ การทางคณิตศาสตร์ (Operator Priority)

มีการลำดบั ความสำคญั ของตัวดำเนินการจากลำดบั สำคัญมากสดุ ไปน้อยสดุ

7. กำหนดให้สแตกของตวั อกั ษรมขี นาด 8 ชอ่ ง โดยเกบ็ ข้อมูลดังนี้

STACK : A, C, D, F, K,__ ,__ ,__

(ใช้ “__ “ เป็นช่องว่างทเ่ี หลืออยู่ใน STACK ) อธบิ ายผลลัพธข์ องสแตกจากการทำงานต่อไปน้ี

a. Pop(STACK, ITEM) e. Pop (STACK, ITEM)

b. Pop(STACK, ITEM) f. Push(STACK , R)

c. Push(STACK , L) g. Push(STACK , S)

d. Push(STACK , P) h. Pop (STACK, ITEM)

8. จงแปลงนพิ จน์ Infix ต่อไปนใี้ ห้อยูใ่ นรปู แบบของนพิ จน์ Postfix ดว้ ยการใช้ขนั้ ตอนวธิ ีของสแตก

8.1 D-B+C/D

8.2 (A*B)+(C*D)

8.3 (A+B)*C-D*F+C

8.4 (A-2)* (B+C-D*E)*F

8.5 A+(C-H) / (B*R)

9. จากโจทย์ขอ้ 8 จงนำนิพจน์ Postfix ทไ่ี ด้ในข้อ 8.1-8.5 แปลงเป็นนพิ จน์ Prefix โดยใช้ขน้ั ตอนวิธี

ของสแตก

10. จงหาคา่ นิพจน์ Postfix ต่อไปนี้โดยการใชข้ น้ั ตอนวิธขี องสแตก

10.1 2 7 5 - * 4 2 ^ +

10.2 9 3 5 + * 2 / 8 – 4 6 9 3 / + * -

10.3 2 7 5 – 3 ^ * 9 -

บทที่ 6
โครงสรา้ งข้อมลู แบบควิ

ควิ เปน็ โครงสร้างข้อมลู แบบเชงิ เส้น ท่ีประกอบไปด้วยสมาชกิ ท่ีเรยี งติดต่อกันเหมือนกับการเข้า
แถวรอคอย ด้วยคุณสมบัติท่ีเดน่ ชัดของการทำงานของโครงสรา้ งขอ้ มลู แบบคิว ถือว่าสงิ่ ใดท่เี ข้ากอ่ นย่อม
ต้องไดร้ ับการทำงานกอ่ น เชน่ การส่ังพิมพ์งานพรอ้ มกันหลายๆ คน โดยใชเ้ ครื่องพิมพเ์ คร่อื งเดียวกนั ทำให้
ระบบจะต้องมีการจัดระบบให้มีการเข้าคิวรอคอยการทำงาน ถ้าใครส่ังพิมพ์ก่อนก็จะเข้าคิวไปรอการ
พิมพ์ในลำดับแรก ใครสั่งเป็นคนต่อไปก็จะต้องเข้าคิวรอจนกว่างานแรกจะทำการพิมพ์เสร็จ จึงจะมา
ทำงานกบั ควิ ทร่ี ออยู่ตอ่ ไป

ในชีวิตประจำวันจะสัมผัสกับระบบคิวหลายอย่าง เช่น รถที่จอดรอสัญญาณไฟ หรือการเข้าคิว
ของคนท่ีมาติดต่อธนาคารเป็นต้น โครงสร้างขอ้ มูลแบบคิวเป็นโครงสร้างที่ปรากฏอยู่โดยท่ัวไป โดยเฉพาะ
อย่างย่ิงในระบบปฏิบัติการคอมพิวเตอร์ ในระบบคมนาคมรวมท้ังในระบบการทดลองดาวเทียมด้วย ใน
สว่ นของคอมพิวเตอร์ที่ใชร้ ะบบการแบง่ เวลา (Timesharing) หากโปรแกรมท่ีมลี ำดบั ความสำคญั
(Priority) เท่ากันจะมกี ารเขา้ ควิ รอการทำงานตามลำดบั ก่อนหลัง

การนำข้อมูลสู่คิว โดยข้อมูลท่ีใส่เข้ามาในคิวจะเข้ามาที่ปลายด้านหลังของคิวที่เรียกว่า
ส่วนท้าย (Rear) และเม่ือต้องการนำข้อมูลออกจากคิว ก็จะทำได้ที่ปลายด้านหน้าของคิวท่ีเรียกว่า
ส่วนหน้า (Front) จึงทำให้หลักการของโครงสร้างข้อมูลแบบคิวมีลักษณะเป็น “เข้าก่อนออกก่อน”
โครงสรา้ งน้ีจงึ ถูกเรียกว่า เป็นโครงสร้างแบบ FIFO (First-In , First-Out)

6.1 การสรา้ งคิว
คิวทีอ่ ย่ใู นคอมพิวเตอรส์ ามารถจัดเก็บไดห้ ลายลกั ษณะแตโ่ ดยทว่ั ไปแลว้ จะใช้การจดั เก็บแบบลิงค์

ลิสต์เดย่ี วหรือจัดเกบ็ โดยใช้อารเ์ รย์
ก่อนทจ่ี ะทำการสร้างควิ จะตอ้ งทำความเขา้ ใจถึงโครงสร้างของคิว ซ่ึงประกอบไปด้วย ตัวควิ ซ่ึง

ในท่ีน้ีขอแทนด้วยอาร์เรย์ ซ่ึงมีสมาชิก N ตัว และจะต้องมีการกำหนดตัวชี้ตำแหน่ง 2 ตัว ได้แก่ ตัวช้ี F
(Front Pointer) เก็บตำแหน่งส่วนปลายด้านหน้า ซ่ึงจะชี้ท่ีสมาชิกตัวแรก และตัวช้ี R (Rear Pointer)
เก็บตำแหน่งปลายด้านหลังซึ่งจะช้ีที่สมาชิกตัวสุดท้ายของคิว โครงสร้างข้อมูลแบบคิวในลักษณะต่างๆ
ดงั ภาพประกอบท่ี 6.1

92

012345
5 4 8 12 14 6

F (Front Pointer) R (Rear Pointer) F= 1 R = 6

a) คิวแบบสมบรู ณ์ 34 5
a) 12 14 6
b) 0 1 2

8

F (Front Pointer) R (Rear Pointer) F= 3 R = 6
b) ควิ แบบไมส่ มบรู ณ์ 345

012
548

F (Front Pointer) R (Rear Pointer) F = 1 R = 3
c) คิวทม่ี ีข้อมูล 3 ตวั

012345

F=0 R=0
d) คิววา่ ง (Empty Queue)

ภาพประกอบที่ 6.1 ตัวอยา่ งโครงสรา้ งข้อมลู แบบคิว

93

6.2 การเพิ่มข้อมูลเข้าสู่คิว
การเพ่ิมข้อมลู เข้าสู่คิว (Insertion Queue) เมือ่ เร่มิ ต้นสรา้ งคิว คิวน้ันไมม่ ีคา่ ใดๆ ยังว่างเปล่า F

และ R จะมีค่าเปน็ 0 ทั้งคู่ การนำขอ้ มูลเข้าสู่คิวจะแบง่ ออกเปน็ 2 กรณี คอื
1. การนำข้อมูลเข้าไปในคิวว่างโดยจะตอ้ งดำเนนิ การให้ตัวชี้ตำแหน่งท้ัง 2 คือ F และ

R ชที้ ่ีชอ่ งแรกหรอื ตำแหน่งทจี่ ะเกบ็ ข้อมลู แรก (F = 1, R=1)
2. การนำข้อมูลเข้าไปในคิวต่อจากข้อมูลเดิม จะต้องจัดการให้ตัวช้ีตำแหน่ง R

ช้ที ต่ี ำแหน่งของข้อมูลถดั ไปท่ีตอ้ งการนำเขา้ (R= R+1) ส่วนพอยนเ์ ตอร์ F ยังคงช้ีท่ีตำแหน่งของข้อมูลที่
นำเขา้ ไปเป็นขอ้ มูลแรก

จากการเพิ่มข้อมูลเข้าสู่คิว สามารถนำเข้ามูลเข้าไปได้หากคิวน้ันมีเน้ือท่ีเหลือสำหรับ
การเพ่ิมข้อมูล ถ้าหากทำการเพ่ิมข้อมูลจนตัวชี้ตำแหน่ง R อยู่ท่ีช่องสุดท้ายแล้ว (R= N) จะไม่สามารถ
ทำการเพิ่มข้อมูลลงคิวได้อีกแสดงว่าคิวเต็ม (Full Queue) ฉะน้ันในกรณีท่ีคิวเต็มแล้วมีการเพ่ิมข้อมูล
เขา้ สคู่ วิ อกี ทำให้เกิดขอ้ ผดิ พลาดขนึ้ เรยี กว่า “Queue Overflow“

ตัวอย่างการเพ่ิมข้อมลู เข้าสูค่ วิ ทบี่ รรจุในอาเรย์ Q ขนาดเท่ากับ 3 (N = 3) กำหนดการ
นำขอ้ มูลเขา้ 3 ตัว ได้แก่ A, B, C ตามลำดับ

1. เมอ่ื คิวว่าง (Empty Queue)
012

F=0 R=0
2. เพ่มิ ข้อมูล A เข้าสู่คิว INSERT (Q , A)

012

A

F=1 R=1
3. เพ่ิมข้อมลู B เขา้ สู่ควิ INSERT (Q , B)

012
AB

F=1 R=2

ภาพประกอบท่ี 6.2 การเพ่ิมข้อมูลเข้าสคู่ ิว

94

4. เพิ่มข้อมูล C เข้าสู่คิว INSERT (Q , C)
012
ABC

F=1 R=3
หลงั จากนจี้ ะเพมิ่ ข้อมูลเข้าควิ อกี ไม่ได้ เน่ืองจากคิวเตม็ คอื R = 3

ภาพประกอบที่ 6.2 การเพ่ิมข้อมูลเขา้ สคู่ วิ (ต่อ)

สรปุ การเพม่ิ ขอ้ มลู เข้าส่คู วิ มีลำดบั ข้นั ตอนการทำงานดงั น้ี
1. ตรวจสอบดูว่าคิวเต็มหรือไม่ กรณีคิวเต็ม ค่าของ R (Rear Pointer) จะเท่ากับขนาด
สูงสุดของตวั แปรอาเรย์ (N) ถ้าควิ เตม็ ควรแจง้ ดว้ ยวา่ “ควิ เตม็ เพิ่มข้อมลู ไม่ได้”
2. ถ้าควิ ยงั วา่ งอยู่ให้ขยบั R ไปชี้ทตี่ ำแหนง่ ถดั ไปหนง่ึ ตำแหนง่ (R= R+1)
3. นำขอ้ มลู ทต่ี ้องการเพ่มิ มาเกบ็ ไว้ท่ตี ำแหน่งใหม่ของ R

ALGORITHM QINSERT ใช้ในการแทรกข้อมูลเข้าควิ โดยท่ี
Q แทน ควิ ทบี่ รรจใุ นอาเรย์
F แทน ตัวชตี้ น้ ควิ
R แทน ตวั ช้ที ้ายคิว
N แทน ขนาดของควิ
X แทน ขอ้ มูลทีจ่ ะแทรก

Pseudo Code 6.1 : QINSERT(Q,N, F, R, X)
This procedure inserts an element X into a queue.
Step 1 [Queue already filled?]

If F = 1 and R = N, or if F = R+1, then Write “Overflow”
Return.
Step 2 [Find new value of REAR]
If F = Null, then Set F = 1 and R =1.
[Queue initially empty.]

else if R = N, then Set R = 1.
else set R = R + 1.

95

Step 3 Set Q[R] = X. [This inserts new element.]
Step 4 Return.

6.3 การนำข้อมูลออกจากคิว
การนำข้อมูลออกจากคิว (Deletion) เป็นการนำข้อมูลที่เก็บอยู่ในคิวออกจากคิว โดยจะนำ

ขอ้ มูลที่ตำแหน่งท่ี F ช้อี ยอู่ อกจากควิ และเมือ่ ทำการนำข้อมูลน้ันออกจากคิวแล้ว จะต้องมีการจดั การให้
ตัวชี้ F ช้ีที่ตำแหน่งต่อจากข้อมูลท่ีได้ทำการนำออกจากคิวไปแล้ว (F= F+1) ส่วนพอยน์เตอร์ R ช้ีไป
ยงั ช่องข้อมูลสดุ ท้ายเหมือนเดิม

แต่สำหรับคิวที่ว่างเปล่า (Empty Queue) จะไม่สามารถนำข้อมูลออกจากคิวได้ ฉะน้ันในกรณี
ที่ควิ ว่างแลว้ มีการนำข้อมลู ออกจากควิ ทำให้เกิดข้อผดิ พลาดขึ้นเรียกว่า “Queue Underflow“

ดังนั้นก่อนท่ีจะทำการนำข้อมูลออกจากคิว ควรที่จะต้องมีการตรวจสอบว่าคิวว่างหรือไม่เพื่อ
ไม่ให้เกิดข้อผิดพลาดน้ีขึ้น จากตัวอย่างในภาพประกอบที่ 6.2 ข้อ 4 เมื่อทำการข้อมูลออกจากคิว
ตามลำดับดงั ได้ดงั น้ี

5. นำขอ้ มูล A ออกจากควิ DELETE (Q)
012
BC

F=2 R=3
6 .นำข้อมูล B ออกจากควิ DELETE (Q)

012
C

F=3 R=3
7. นำขอ้ มลู C ออกจากควิ DELETE (Q)

012

F=0 R=0
หลงั จากนี้จะนำขอ้ มลู ออกจากคิวอีกไม่ได้ เนื่องจากคิวว่าง คอื F = 0 , R = 0

ภาพประกอบที่ 6.3 การนำข้อมลู ออกจากควิ

96

สรุปการนำข้อมูลออกจากควิ มลี ำดบั ข้ันตอนการทำงานดงั น้ี
1. ตรวจสอบดกู อ่ นว่า คิวว่างหรือไม่ ถ้าคิววา่ งใหแ้ จ้งว่า “ควิ ว่างนำข้อมูลออกไม่ได้”
2. ถา้ ควิ ไมว่ ่าง ใหน้ ำข้อมูลท่ีตำแหน่ง F ออกมา
3. ตรวจสอบดวู า่ ข้อมูลทถี่ กู นำออกมาเป็นข้อมลู ตวั สุดท้ายในควิ หรือไม่เพ่ือตรวจสอบว่า
F = R หรอื ไม่
a. ถ้า F = R นั่นคือ ข้อมูลที่ถูกนำออกมาเป็นตัวสุดท้าย แสดงว่าคิวว่าง ให้
กำหนดคา่ F = 0 และ R = 0
b. ถ้า F ≠ R น่ันคอื คิวไม่วา่ งใหข้ ยับตำแหน่งของ F (F= F+1)

ALGORITHM QDELETE ใช้ในการลบข้อมลู ออกจากควิ โดยที่
Q แทน ควิ ทีบ่ รรจใุ นอาเรย์
F แทน ตวั ชีต้ น้ คิว
R แทน ตวั ช้ที า้ ยควิ
Y แทน เกบ็ คา่ ขอ้ มลู ทีจ่ ะลบออกจากคิว
N แทน ขนาดของคิว

Pseudo Code 6.2: QDELETE(Q,N,F,R,X) This procedure deletes an element
from a queue and assigns it to the variable X.
Step 1 [ Queue already empty?]

If F = Null, then Write “Underflow”
Return.
Step 2 Set X = Q[F].
Step 3 [Find new value of Front.]
If F = R then Set F = Null and R = Null.
[Queue has only one element to start.]
Else If F = N then Set F = 1.

Else Set = F + 1 .
Step 4 Return.


Click to View FlipBook Version