รายการ(List) [1] ผู้สอน อาจารย์ ยืนยง กันทะเนตร สาขาวิชาเทคโนโลยีคอมพิวเตอร์เคลื่อนที่ คณะเทคโนโลยีสารสนเทศและการสื่อสาร Website : ict.up.ac.th/yeunyong
หัวข้อวันนี้ Introduction ADT of List - Value Definition, Operation Definition Implementation of List (โดยใช้อาร์เรย์) ปัญหาของอาร์เรย์ ลิงค์ลิสต์ (Linked List) โครงสร้างของลิงค์ลิสต์ การประกาศโครงสร้างข้อมูลชนิดลิงค์ลิสต์ การสร้างตัวแปรเพื่อใช้งาน การกำหนดค่าให้กับข้อมูล วิธีการเชื่อมโยง node เข้าด้วยกัน
Introduction จริงๆ แล้ว ลิสต์ คือข้อมูลพื้นฐาน เป็นนิยามเบื้องต้นของการเก็บข้อมูลในลักษณะ “เป็นแถวเรียงต่อกันไป” - ความสัมพันธ์แบบเชิงเส้น แต่เป็นลักษณะของข้อมูลที่แตกต่างจากอาร์เรย์ ข้อมูลต้องเรียงเป็นแถวจริงๆ ไม่มีช่องว่าง เหมาะกับบางปัญหามากกว่าอาร์เรย์ นำไปประยุกต์ใช้ในหลายๆ ทาง เช่น stack, queue, database, game
ADT : Value Definition ข้อมูลที่จะเก็บในลิสต์จะมีชนิดเป็นอย่างไรก็ได้ ขึ้นอยู่กับว่าเราจะเก็บข้อมูลอะไร เช่นเดียวกับ stack และ queue โครงสร้างมีความสัมพันธ์แบบเชิงเส้น ข้อมูลถูกเก็บเป็นแถวเรียงต่อกันไป การนำข้อมูลเข้า, นำข้อมูลออก กระทำที่ตำแหน่งใดในโครงสร้างก็ได้
ADT : Operation Definition insert – การเพิ่มข้อมูลลงในลิสต์ delete – การลบข้อมูลออกจากลิสต์ traverse (การท่องไปในลิสต์) – การเข้าถึงสมาชิกตัวแรกของลิสต์ไปจนถึงตัวสุดท้าย (ตามลำดับ) ท่องเพื่อค้นหาข้อมูล, เพิ่มข้อมูล หรือลบข้อมูล ณ ตำแหน่งโหนดใดๆ ในลิสต์ บางตำราก็ไม่นับเป็น Operation ขึ้นกับการประยุกต์
Implementation of List (โดยใช้ array)
ปกติเวลาสร้าง list มักจะมีการ insert และ delete ข้อมูลใน list หลากหลายรูปแบบ ขึ้นอยู่กับว่าเอาลิสต์ไปเก็บข้อมูลแบบไหน เช่น เก็บข้อมูลนิสิต – ข้อมูลต้องเรียงลำดับตามรหัส อาจมีการ insert ข้อมูลแทรกในลำดับที่ถูกต้อง การ delete จะ delete ข้อมูลตัวที่ต้องการ เช่น เก็บข้อมูลหัวข้อข่าวประจำวัน – ข้อมูลต้องเรียงลำดับตามวันที่ การ insert (ปกติ) ข้อมูลจะต่อท้ายลิสต์ การ delete (ปกติ) จะ delete ข้อมูลด้านหน้าลิสต์
การสร้างลิสต์แบบพื้นฐานก็สามารถใช้อาร์เรย์เป็นลิสต์ สมาชิกตัวแรกของลิสต์อยู่ที่ตำแหน่งอาร์เรย์ช่องที่ 0 สมาชิกตัวที่ 2 อยู่ช่องที่ 1 ตามลำดับไปเรื่อยๆ ข้อดี - การท่อง (เพื่อหาข้อมูล) ทำได้ง่ายโดยผ่าน index ของอาร์เรย์ ข้อเสีย - การ insert และ delete ทำได้ยาก ข้อมูลต้องเรียงอยู่เต็มทุกช่องในลิสต์ การเพิ่ม ลบ จะทำให้ต้องมีการเลื่อนข้อมูลหลายตัว
2 4 6 8 9 2 4 6 8 9 3 ข้อมูลตัวใหม่ delete(2,list1) 2 3 4 6 8 9 Example ให้ list1 เป็นลิสต์ของข้อมูลซึ่งเรียงจากน้อยไปหามากซึ่งสร้างจากอาร์เรย์ขนาด 8 ช่อง และมีข้อมูลในลิสต์ ดังนี้ Insert(3,list1) 2 4 6 8 9 2 4 6 8 9 3 ข้อมูลตัวใหม่ delete(2,list1) 2 3 4 6 8 9
ปัญหาของลิสต์ (และอาร์เรย์) การเขียนโปรแกรมสร้างโครงสร้างข้อมูลที่ผ่านมามีลักษณะการโปรแกรมโดยประยุกต์ใช้อาร์เรย์ในการสร้าง เรียกว่าการโปรแกรมแบบ static memory allocation การใช้งานของโครงสร้างบางอย่างถูกจำกัด Insert/delete ข้อมูลที่อยู่ระหว่างข้อมูลอื่นๆ ลำบาก เพราะลบแต่ “ข้อมูล” แต่ไม่ได้ลบ “ช่อง” ที่เก็บข้อมูล ไม่สามารถแก้ไขขนาดของโครงสร้างได้ จำกัดตามขนาดของอาร์เรย์ที่นำมาใช้
ลิงค์ลิสต์ (Linked List) แก้ปัญหาบางอย่างที่อาร์เรย์ไม่ถนัด หลักการ – ไม่จองเนื้อที่ในการเก็บข้อมูลไว้ เมื่อจะใช้ (insert) ก็จองหน่วยความจำเพิ่ม เมื่อเลิกใช้ (delete) ก็คืนหน่วยความจำ สามารถเพิ่ม/ลบข้อมูลในโครงสร้างได้เรื่อยๆ ตราบใดที่ยังมีหน่วยความจำเหลืออยู่ เรียกว่าการโปรแกรมแบบ dynamic memory allocation
โครงสร้างของลิงค์ลิสต์ ลิงค์ลิสต์ ประกอบด้วยกลุ่มของข้อมูลที่เรียงต่อกันเป็นสาย โดยข้อมูลแต่ละตัวจะเรียกว่า โหนด (node) ในแต่ละโหนดจะประกอบด้วยส่วนประกอบ 2 ส่วน คือ ส่วนเก็บข้อมูล (data, info) – เป็นส่วนที่ใช้ในการเก็บข้อมูล ซึ่งอาจมีข้อมูลมากกว่าหนึ่งชนิดก็ได้ เช่น ประวัตินิสิต เป็นต้น ส่วนที่ชี้ไปยังโหนดถัดไป (next, link) – เป็นพอยน์เตอร์ที่ชี้ไปยังโหนดตัวถัดไป
อาจมีตัวแปร pointer เพื่อชี้ตำแหน่ง node แรกในลิงค์ลิสต์ ณ โหนดสุดท้ายส่วน next จะชี้ไปที่ NULL
ตัวอย่างลักษณะการจัดเก็บลิงค์ลิสต์ในหน่วยความจำ NULL NULL Header
การประกาศโครงสร้างข้อมูลชนิดลิงค์ลิสต์ การประกาศโครงสร้างข้อมูลแบบลิงค์ลิสต์มักจะประกาศเป็นตัวแปรแบบ structure ที่ประกอบไปด้วยข้อมูล 2 ส่วน คือ data ( ซึ่งอาจประกอบด้วยข้อมูลหลายตัวก็ได้ ) และ next ดังตัวอย่าง struct list{ char id [10] ; int mark ; struct list *next ; } ; typedef struct list node ; data *next ข้อมูล ตัวชี้ไปยังโหนดถัดไป
การสร้างตัวแปรเพื่อใช้งาน 1. struct list { 2. char id[10] ; 3. int mark ; 4. struct list *next ; 5. } ; 6. typedef struct list node ; 7. node *head ; 8. head = new node ; *next mark id head เป็นการประกาศตัวแปร head เป็นตัวแปรแบบ pointer ซึ่งชี้ไปยังข้อมูลชนิดโครงสร้างที่ชื่อ node เป็นการจองพื้นที่หน่วยความจำสำหรับโหนดใหม่ที่จะเก็บข้อมูลลงไป (คำสั่งของ C++)
การกำหนดค่าให้กับข้อมูล คำสั่ง ภาพของหน่วยความจำ strcpy(head->id, “46xx”) ; head->mark = 30 ; head->next = NULL ; (next เป็นตัวแปร pointer) *next mark 46xx head *next 30 46xx head 30 46xx head
วิธีการเชื่อมโยง node เข้าด้วยกัน struct list { int data ; struct list *next; } ; typedef struct list node ; node *head, *p , *q ; head = new node ; p = new node ; q = new node ; head->data = 1; p->data = 2 ; q ->data = 3 ; *next 1 head *next 2 p *next 3 q
วิธีการเชื่อมโยง node เข้าด้วยกัน head->next = p ; p->next = q ; q->next = NULL ; 1 *next 2 p head 1 2 p head *next 3 q 1 2 p head 3 q
การแสดงวิธีการเชื่อมโยงลิงค์ลิสต์ที่ผ่านมาเป็นเพียงตัวอย่างง่ายๆ เท่านั้น ในการใช้งานจริง ไม่สามารถทำได้ เพราะจำนวนตัวแปรที่กำหนดให้โปรแกรมมีจำกัด ในขณะที่จำนวน node สามารถเพิ่มได้ไม่จำกัด จะใช้วิธีการเขียนเป็นฟังก์ชันเพื่อเพิ่มจำนวน node เข้าไปในลิงค์ลิสต์ทีละ 1 node ซึ่งเมื่อทำการเชื่อมโยงแล้ว node อื่นๆ นอกจาก head ไม่จำเป็นต้องมีตัวแปรกำกับ