14
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 knowledge society

linked lists - FEUsci.feu.ac.th/faa/dsa/Linked lists.pdf · Title: linked lists Author: neramit xumsai na ayudhya Subject: Data Structures and Algorithms Keywords: dsa Created Date:

  • Upload
    others

  • View
    17

  • Download
    0

Embed Size (px)

Citation preview

  • 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