บทที่ 4 ลิงค์ลิสต์

Download Report

Transcript บทที่ 4 ลิงค์ลิสต์

บทที ่ 4 ลิงค์ลิสต์ (Link-list)
1
บทที่ 4 ลิงค์ลสิ ต์ (Link-list)
•
•
•
•
•
•
•
•
ลิงค์ลสิ ต์ทศิ ทางเดียว (Singly Link List)
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การนาข้อมูลในลิงค์ลสิ ต์ทศิ ทางเดียวออกมาแสดงผล
การเปลีย่ นโครงสร้างลิงค์ลสิ ต์ทศิ ทางเดียว
ลิงค์ลสิ ต์แบบสองทิศทาง (Doubly Linked List)
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การนาลิงค์ลสิ ต์ไปใช้งาน
สรุปเนื้อหาบทที่ 4
2
ลิงค์ลสิ ต์ทศิ ทางเดียว (Singly Link List)
• ลิงค์ลสิ ต์เป็ นชนิดข้อมูลทีส่ ามารถเพิม่ และลดขนาดในการเก็บข้อมูลได้แบบอัตโนมัติ ทาให้
ไม่ตอ้ งจองพืน้ ทีใ่ นหน่วยความจาก่อนใช้งาน
• โครงสร้างแบบลิงค์ลิสต์ท่ใี ช้สาหรับเก็บข้อมูล เรียกว่า โหนด (Node) ภายในโหนดมี
ส่วนประกอบอย่างน้อยสองส่วนคือ
o ส่วนเก็บข้อมูล (item) ทาหน้าทีเ่ ก็บข้อมูลภายในโหนด
o ส่วนเชื่อมโยง (next) ทาหน้าทีเ่ ชือ่ งโยงโหนดภายในลิงค์ลสิ ต์
• โครงสร้างของลิงค์ลสิ ต์ ในภาษา Java และภาษา C
Java
1
2
3
4
public class Node{
private Object item;
private Node next;
}
C
1
2
3
4
struct Node{
int item;
struct Node *next;
}
3
ลิงค์ลสิ ต์ทศิ ทางเดียว (Singly Link List)
การสร้างและใช้งานลิงค์ลิสต์ทิศทางเดียวในภาษา Java
ตัวอย่างที่ 4.1 คลาส Node เป็ นโครงสร้างลิงค์ลสิ ต์ทศิ ทางเดียว
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package LinkedList;
public class Node{
private Object item;
private Node next;
//begin constructor
public Node() {
next = null;
}
public Node(Object newItem){
item = newItem;
next = null;
}
public Node(Object newItem,Node nextNode){
item = newItem;
next = nextNode;
}//end constructor
//begin method
public void setItem(Object newItem){
item = newItem;
}
public Object getItem (){
return item;
}
public void setNext(Node nextNode){
next = nextNode;
}
public Node getNext() {
return next;
}
}
4
ลิงค์ลสิ ต์ทศิ ทางเดียว (Singly Link List)
การสร้างและใช้งานลิงค์ลิสต์ทิศทางเดียวในภาษา Java
ตัวอย่างที่ 4.2 การเรียกใช้งานคลาส Node ในภาษา Java
1
2
3
4
5
6
7
package LinkedList;
public class UseNode{
public static void main(String[] args){
Node n = new Node(9);
Node first = new Node(19,n);
}
}
สร้างโหนดใหม่อา้ งอิงด้วย n
สร้างโหนดใหม่อา้ งอิงด้วย first และ
เชือ่ มโยงไปยังโหนด n อ้างอิง
• สัญลักษณ์โหนดสุดท้ายของลิงค์ลสิ ต์ (โหนดทีไ่ ม่การเชือ่ มไปยังโหนดถัดไป)
จะสัญลักษณ์
5
ลิงค์ลสิ ต์ทศิ ทางเดียว (Singly Link List)
การสร้างและใช้งานลิงค์ลิสต์ทิศทางเดียวในภาษา C
• ภาษา C จะใช้พอร์ตเตอร์ทาหน้าทีอ่ า้ งอิงไปยังโหนถัดไป
• ใช้ฟงั ก์ชนั malloc( ) เป็ นฟงั ก์ชนั ในการจัดการบล็อกหน่วยความจา
• ใช้ตวั แปรแบบพอร์ตเตอร์อา้ งอิงบล็อกหน่วยความจาใหม่ทส่ี ร้างขึน้
6
ลิงค์ลสิ ต์ทศิ ทางเดียว (Singly Link List)
การสร้างและใช้งานลิงค์ลิสต์ทิศทางเดียวในภาษา C
ตัวอย่างที่ 4.3 ฟงั ก์ชนั Node โครงสร้างลิงค์ลสิ ต์ทศิ ทางเดียวของภาษา C
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
//structure Link List
struct Node{
int item;
struct Node *next;
};
//Function insert new node in Link List
struct Node *insertNode(int newItem,struct Node *nextNode){
struct Node *newNode;
newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->item = newItem;
newNode->next = nextNode;
return(newNode);
}
7
ลิงค์ลสิ ต์ทศิ ทางเดียว (Singly Link List)
การสร้างและใช้งานลิงค์ลิสต์ทิศทางเดียวในภาษา C
ตัวอย่างที่ 4.4 ฟงั ก์ชนั เรียกฟงั ก์ชนั Node มาใช้งานในภาษา C
1
2
3
4
5
6
void main(){
struct Node *n = NULL;
struct Node *first = NULL;
n = insertNode(9,NULL);
first = insertNode(19,n);
}
สร้างโหนดใหม่อา้ งอิงด้วย n
สร้างโหนดใหม่อา้ งอิงด้วย first และ
เชือ่ มโยงไปยังโหนด n อ้างอิง
8
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การสร้างส่วนหัวของลิงค์ลิสต์ทิศทางเดียว
• จุดเริม่ ต้นในการเข้าถึงข้อมูลในลิงค์ลสิ ต์ จะถูกเรียกว่า ส่วนหัว (head)
ตัวอย่างที่ 4.5 ขันตอนวิ
้
ธกี ารสร้างส่วนหัวและการเพิม่ โหนดในลิงค์ลสิ ต์ทศิ ทางเดียว
9
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การสร้างส่วนหัวของลิงค์ลิสต์ทิศทางเดียว
ตัวอย่างที่ 4.5 (ต่อ) ขันตอนวิ
้
ธกี ารสร้างส่วนหัวและการเพิม่ โหนดในลิงค์ลสิ ต์ทศิ ทางเดียว
10
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การค้นหาตาแหน่ งโหนดที่ต้องลบหรือแทรกโหนดในลิงค์ลิสต์ทิศทางเดียว
• ตัวแปรทีเ่ กีย่ วข้องการค้นหาตาแหน่งโหนดมีอยู่ 2 ตัว
o ตัวแปร curr ทาหน้าทีค่ น้ หาตาแหน่งโหนดทีต่ อ้ งการลบหรือแทรกโหนด
o ตัวแปร prev ทาหน้าทีอ่ า้ งอิงตาแหน่งโหนดก่อนหน้าทีต่ อ้ งการลบหรือแทรกโหนด
ตัวอย่างที่ 4.6 อัลกอริทมึ ค้นหาตาแหน่งโหนดในลิงค์ลสิ ต์
Java
1
2
3
4
5
6
7
8
9
10
11
12
Node curr = new Node();
Node prev = new Node();
curr = head;
prev = null;
while (curr != null){
if (curr.getItem() == ข้อมูลทีต่ อ้ งการค้นหา){
//ทาการลบหรือแทรกโหนด
}else{
prev = curr;
curr = curr.getNext();
}
}
11
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การค้นหาตาแหน่ งโหนดที่ต้องลบหรือแทรกโหนดในลิงค์ลิสต์ทิศทางเดียว
ตัวอย่างที่ 4.6 (ต่อ) อัลกอริทมึ ค้นหาตาแหน่งโหนดในลิงค์ลสิ ต์
C
1
2
3
4
5
6
7
8
9
10
11
12
struct Node *curr;
struct Node *prev;
curr = head;
prev = NULL;
while (curr != NULL){
if (curr->item == ข้อมูลทีต่ อ้ งการค้นหา){
//ทาการลบหรือแทรกโหนด
}else{
prev = curr;
curr = curr->next;
}
}
12
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การค้นหาตาแหน่ งโหนดที่ต้องลบหรือแทรกโหนดในลิงค์ลิสต์ทิศทางเดียว
ตัวอย่างที่ 4.7 แสดงการค้นหาตาแหน่งโหนดทีม่ คี า่ ข้อมูลเท่ากับ 6 ในลิงค์ลสิ ต์
13
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การลบโหนดในลิงค์ลิสต์ทิศทางเดียว
• ก่อนทีจ่ ะลบโหนดในลิงค์ลสิ ต์ได้ตอ้ งค้นหาโหนดทีต่ อ้ งการลบเสียก่อน โดยทีต่ วั แปร curr
และ prev จะทาหน้าทีอ่ า้ งอิงตาแหน่งโหนดในลิงค์ลสิ ต์
o การลบโหนดระหว่างข้อมูลที่มีอยู่ในลิงค์ลิสต์ทิศทางเดียว
curr
อ้างอิงตาแหน่งโหนดทีต่ อ้ งการลบ
prev
อ้างอิงตาแหน่งโหนดก่อนหน้าทีต่ อ้ งการลบ
Java
C
prev.setNext(curr.getNext()); prev->next = curr->next;
14
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การลบโหนดในลิงค์ลิสต์ทิศทางเดียว
o การลบโหนดระหว่างข้อมูลที่มีอยู่ในลิงค์ลิสต์ทิศทางเดียว
เพือ่ ให้เข้าใจมากขึน้ ในขันตอนในการลบโหนดในลิ
้
งค์ลสิ ต์ ได้แสดงการนาตัวแปร buff มาทา
หน้าทีอ่ า้ งอิงในตาแหน่งโหนดก่อนหน้าทีต่ อ้ งการลบ
Java
1
2
C
Node buff = curr.getNet(); struct Node *buff = curr->next;
prev.setNext(buff);
prev->next = buff;
15
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การลบโหนดในลิงค์ลิสต์ทิศทางเดียว
o การลบโหนดที่เป็ นส่วนหัวในลิงค์ลิสต์ทิศทางเดียว
curr อ้างอิงตาแหน่งโหนดทีต่ อ้ งการลบ
prev มีคา่ เท่ากับ null คือไม่อา้ งอิงโหนดใดๆ
Java
head = curr.getNext();
C
head = curr->next;
16
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การลบโหนดในลิงค์ลิสต์ทิศทางเดียว
o การลบโหนดตาแหน่ งสุดท้ายของลิงค์ลิสต์ทิศทางเดียว
curr อ้างอิงตาแหน่งโหนดทีต่ อ้ งการลบและเป็ นตาแหน่งโหนดสุดท้ายในลิงค์ลสิ ต์
prev อ้างอิงตาแหน่งโหนดก่อนหน้าทีต่ อ้ งการลบ
Java
prev.setNext(null);
รอ
C
prev->next = NULL;
รอ
prev.setNext(curr.getNext()); prev->next = curr->next;
17
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การเพิ่มโหนดในลิงค์ลิสต์ทิศทางเดียว
o การเพิ่มโหนดระหว่างข้อมูลที่มีอยู่ในลิงค์ลิสต์ทิศทางเดียว
curr อ้างอิงตาแหน่งโหนดก่อนหน้าโหนดทีจ่ ะแทรก
prev อ้างอิงตาแหน่งโหนดหลังโหนดทีจ่ ะแทรก
Java
1
2
3
C
newNode =
Node newNode = new Node(8);
insertNode(8,NULL);
newNode.setNext(curr);
newNode->next = curr;
prev.setNext(newNode);
prev->next = newNode;
18
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การเพิ่มโหนดในลิงค์ลิสต์ทิศทางเดียว
o การเพิ่มโหนดในตาแหน่ งที่เป็ นส่วนหัวลิงค์ลิสต์ทิศทางเดียว
curr อ้างอิงตาแหน่งโหนดทีต่ อ้ งการแทรกและเป็ นตาแหน่งโหนดทีเ่ ป็ นส่วนหัว
prev ไม่อา้ งอิงตาแหน่งโหนดใดๆ โดยมีคา่ เท่ากับ null
Java
1
2
3
C
newNode =
Node newNode = new Node(3);
insertNode(3,NULL);
newNode.setNext(curr);
newNode->next = curr;
head = newNode;
head = newNode;
19
การจัดการลิงค์ลสิ ต์ทศิ ทางเดียว
การเพิ่มโหนดในลิงค์ลิสต์ทิศทางเดียว
o การเพิ่มโหนดในตาแหน่ งสุดท้ายของลิงค์ลิสต์ทิศทางเดียว
curr ไม่อา้ งอิงตาแหน่งโหนดใดๆ โดยมีคา่ เท่ากับ null
prev อ้างอิงตาแหน่งโหนดสุดท้ายในลิงค์ลสิ ต์
Java
1
2
C
Node newNode = new Node(3); newNode = insertNode(3,NULL);
prev.setNext(newNode);
prev->next = newNode;
20
การนาข้อมูลในลิงค์ลสิ ต์ทศิ ทางเดียวออกมาแสดงผล
• การนาข้อมูลในลิงค์ลสิ ต์ออกมาแสดงผลหรือเรียกว่าการท่องเข้าไปในลิงค์ลสิ ต์
• การท่องในลิงค์ลสิ ต์จะเข้าไปทีล่ ะโหนดตัง้ แต่โหนดแรกสุดทีอ่ า้ งอิงด้วยตัวแปร head จนถึง
โหนดสุดท้ายของลิงค์ลสิ ต์
• ตาแหน่ งโหนดสุดท้ายของลิงค์ลสิ ต์คอื การเชื่องโยงโหนดถัดไป (ตัวแปร next) จะมีค่า
เท่ากับ null
ตัวอย่างที่ 4.8 อัลกอริทมึ นาข้อมูลในลิงค์ลสิ ต์ทศิ ทางเดียวออกมาแสดงผล
Java
1
2
3
4
5
6
Node curr = new Node();
curr = head;
while (curr != null){
System.out.println(curr.getItem());
curr = curr.getNext();
}
C
struct Node *curr;
curr = head;
while (curr != NULL){
printf("%d\t",curr->item);
curr = curr->next;
}
21
การเปลีย่ นโครงสร้างลิงค์ลสิ ต์ทศิ ทางเดียว
การอ้างอิงส่วนท้าย (Tail References)
• เป็ นการเพิม่ ตัวแปรทีท่ าหน้าทีพ่ เิ ศษในการอ้างอิงตาแหน่งสุดท้ายในลิงค์ลสิ ต์
• การอ้างอิงส่วนท้ายสามารถนามาเพิม่ ประสิทธิภาพในการท่องเข้าไปในลิงค์ลสิ ต์
o ให้ทราบว่าในการท่องเข้าไปในลิงค์ลสิ ต์นนั ้ เป็ นตาแหน่งสิน้ สุดของลิงค์ลสิ ต์แล้วหรือไม่
o เมื่อต้องการเพิม่ หรือลบข้อมูลของลิงค์ลสิ ต์ในตาแหน่ ง โหนดสุดท้ายก็สามารถทาได้
ทันที โดยไม่ตอ้ งท่องเข้าไปในลิงค์ลสิ ต์ทลี ะโหนดจากโหนดแรก
22
การเปลีย่ นโครงสร้างลิงค์ลสิ ต์ทศิ ทางเดียว
ดัมมีโหนด (Dummy Node)
• บางครัง้ การใช้ง านลิง ค์ลิส ต์ต้อ งบอกถึง ที่ม าในการสร้า งลิง ค์ลิส ต์ หรือ บอกถึง รูป แบบ
โครงสร้างของลิงค์ลสิ ต์วา่ เป็ นอย่างไร เพือ่ ให้ผทู้ น่ี าลิงค์ลสิ ต์ไปใช้ง านเข้าใจถึงข้อมูลภายใน
ลิงค์ลสิ ต์ได้ดขี น้ึ โดยการเพิม่ โหนดทีท่ าหน้าทีบ่ อกรายละเอียดและโครงสร้างของลิงค์ลสิ ต์
ซึง่ เรียกโหนดทีท่ าหน้าทีน่ ้วี า่ ดัมมีโหนด (Dummy Node)
• ดัมมีโหนด (Dummy Node) เป็ นโหนดทีอ่ ยูใ่ นตาแหน่งหัวของลิงค์ลสิ ต์ โดยลักษณะของการ
เก็บข้อมูลในดัมมีโหนดจะมีลกั ษณะไม่เหมือนกับการเก็บข้อมูลในโหนดอื่นๆ ของลิงค์ลสิ ต์
23
การเปลีย่ นโครงสร้างลิงค์ลสิ ต์ทศิ ทางเดียว
ลิงค์ลิสต์แบบวงกลม (Circular Linked List)
เมื่อท่องเข้าไปจนถึงตาแหน่ งสุดท้ายของลิงค์ลิสต์แล้วต้องการกลับไปยัง โหนดเริม่ ต้น ต้อง
กลับไปทีต่ าแหน่งของจุดเริม่ ต้นของลิงค์ลสิ ต์ใหม่คอื ตาแหน่ ง head แล้วจึงท่องเข้าไปในลิงค์
ลิสต์ได้อกี ครัง้ จากปญั หานี้สามารถแก้ไขได้ดว้ ยการเปลีย่ นรูปแบบการเชื่อมโยงของโหนดให้
เป็ นรูปแบบโครงสร้างลิงค์ลสิ ต์แบบวงกลม
24
การเปลีย่ นโครงสร้างลิงค์ลสิ ต์ทศิ ทางเดียว
ลิงค์ลิสต์แบบวงกลม (Circular Linked List)
ตัวอย่างที่ 4.9 สร้างลิงค์ลสิ ต์ทศิ ทางเดียวแบบวงกลม
25
การเปลีย่ นโครงสร้างลิงค์ลสิ ต์ทศิ ทางเดียว
ลิงค์ลิสต์แบบวงกลม (Circular Linked List)
ตัวอย่างที่ 4.9 (ต่อ) สร้างลิงค์ลสิ ต์ทศิ ทางเดียวแบบวงกลม
26
ลิงค์ลสิ ต์แบบสองทิศทาง (Doubly Linked List)
การอ้างอิงโหนดในลิงค์ลสิ ต์แบบทิศทางเดียว (Singly Linked List) สามารถท่องเข้าไปในลิงค์
ลิสต์ได้จากโหนดเริม่ ต้นไปจนถึงโหนดสุดท้ายของลิงค์ลสิ ต์ ไม่สามารถย้อนกลับจากโหนด
สุดท้ายกลับไปหาโหนดแรกได้ จากปญั หาการท่องกลับในลิงค์ลสิ ต์จงึ มีการพัฒนาโครงสร้างการ
เชือ่ มโยงภายในลิงค์ลสิ ต์ให้มกี ารเชือ่ มโยงแบบย้อนกลับ ซึง่ เป็ นลักษณะโครงสร้างของลิงค์ลิสต์
แบบสองทิศทาง (Doubly Linked List)
โดยที่ item
เป็ นตัวแปรเก็บข้อมูลของโหนด
next
ทาหน้าทีอ่ า้ งอิงไปยังโหนดถัดไป
precede ทาหน้าทีอ่ า้ งอิงไปยังโหนดก่อนหน้า
27
ลิงค์ลสิ ต์แบบสองทิศทาง (Doubly Linked List)
Java
1
2
3
4
5
public class DoubleLink{
private Object item;
private DoubleLink next;
private DoubleLink precede;
}
C
1
2
3
4
5
struct DoubleLink{
int item;
struct DoubleLink *next;
struct DoubleLink *precede
}
28
ลิงค์ลสิ ต์แบบสองทิศทาง (Doubly Linked List)
โครงสร้างลิงค์ลิสต์แบบสองทิศภาษา Java
ตัวอย่างที่ 4.10 คลาส DoubleLink โครงสร้างลิงค์ลสิ ต์แบบสองทิศทางภาษา Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package LinkedList;
public class DoubleLink{
private Object item;
private DoubleLink next;
private DoubleLink precede;
public DoubleLink(){
next = null;
precede = null;
}
public DoubleLink(Object newItem){
item = newItem;
next = null;
precede = null;
}
public DoubleLink(Object newItem,DoubleLink nextNode,DoubleLink precedeNode){
item = newItem;
next = nextNode;
precede = precedeNode;
} //end constructor
public void setItem(Object newItem){
item = newItem;
}
public Object getItem(){
return item;
}
public void setNext(DoubleLink nextNode){
next = nextNode;
}
public DoubleLink getNext() {
return next;
}
public void setPrecede(DoubleLink precedeNode){
precede = precedeNode;
}
public DoubleLink getPrecede(){
return precede;
}
}
29
ลิงค์ลสิ ต์แบบสองทิศทาง (Doubly Linked List)
โครงสร้างลิงค์ลิสต์แบบสองทิศภาษา Java
ตัวอย่างที่ 4.11 การเรียกใช้งานคลาส DoubleLink ในภาษา Java
1
2
3
4
5
6
7
8
package LinkedList;
public class UseDoubleLink{
public static void main(String[] args){
DoubleLink n = new DoubleLink(6);
DoubleLink first = new DoubleLink(9,n,null);
n.setPrecede(first);
}
}
สร้างโหนดใหม่อา้ งอิงด้วย n
สร้างโหนดใหม่อา้ งอิงด้วย first
และเชือ่ มโยงโหนด n เป็ นโหนดถัดไป
กาหนดให้โหนด n อ้างอิงย้อนกลับไปยังโหนด first
30
ลิงค์ลสิ ต์แบบสองทิศทาง (Doubly Linked List)
โครงสร้างลิงค์ลิสต์แบบสองทิศภาษา C
ตัวอย่างที่ 4.12 อัลกอริทมึ การประกาศและกาหนดค่าให้กบั ลิงค์ลสิ ต์แบบสองทิศทางภาษา C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
//structure DoubleLinkList
struct DoubleLink{
int item;
struct DoubleLink *next;
struct DoubleLink *precede;
};
//Function insert node in DoubleLinkList
struct DoubleLink *insertNode(int newItem,struct DoubleLink *nextNode,
struct DoubleLink *precedeNode){
struct DoubleLink *newNode;
newNode = (struct DoubleLink *)malloc(sizeof(struct DoubleLink));
newNode->item = newItem;
newNode->next = nextNode;
newNode->precede = precedeNode;
return(newNode);
}
31
ลิงค์ลสิ ต์แบบสองทิศทาง (Doubly Linked List)
โครงสร้างลิงค์ลิสต์แบบสองทิศภาษา C
ตัวอย่างที่ 4.13 การเรียกใช้ฟงั ก์ชนั DoubleLink ในภาษา C
1
2
3
4
5
6
7
void main(){
struct DoubleLink *n = NULL;
struct DoubleLink *first = NULL;
n = insertNode(6,NULL,NULL);
first = insertNode(9,n,NULL);
n->precede = first;
}
สร้างโหนดใหม่อา้ งอิงด้วย n
สร้างโหนดใหม่อา้ งอิงด้วย first
และเชือ่ มโยงโหนด n เป็ นโหนดถัดไป
กาหนดให้โหนด n อ้างอิงย้อนกลับไปยังโหนด first
32
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การค้นหาตาแหน่ งโหนดในลิงค์ลิสต์แบบสองทิศทาง
 prev1 ทาหน้าทีอ่ า้ งอิงโหนดก่อนหน้าทีต่ อ้ งการค้นหา
 prev2 ทาหน้าทีอ่ า้ งอิงโหนดถัดไปทีต่ อ้ งการค้นหา
 curr ทาหน้าอ้างอิงข้อมูลในลิงค์ลสิ ต์
33
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การค้นหาตาแหน่ งโหนดในลิงค์ลิสต์แบบสองทิศทาง
ตัวอย่างที่ 4.14 อัลกอริทมึ ค้นหาตาแหน่งโหนดในลิงค์ลสิ ต์แบบสองทิศทาง
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DoubleLink curr = new DoubleLink();
DoubleLink prev1 = new DoubleLink();
DoubleLink prev2 = new DoubleLink();
curr = head;
prev1 = null;
prev2 = null;
while (curr != null){
if (curr.getItem()== ข้อมูลทีต่ อ้ งการค้นหา){
prev2 = curr.getNext();
//ลบหรือแทรกโหนด
}else{
prev1 = curr;
curr = curr.getNext();
}
}
34
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การค้นหาตาแหน่ งโหนดในลิงค์ลิสต์แบบสองทิศทาง
ตัวอย่างที่ 4.14 (ต่อ) อัลกอริทมึ ค้นหาตาแหน่งโหนดในลิงค์ลสิ ต์แบบสองทิศทาง
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Node *curr;
struct Node *prev1;
struct Node *prev2;
curr = head;
prev1 = NULL;
prev2 = NULL;
while (curr != NULL){
่ อ้ งการค้นหา){
if (curr->item == ข้อมูลทีต
prev2 = curr->next;
//ลบหรือแทรกโหนด
}else{
prev1 = curr;
curr = curr->next;
}
}
35
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การลบโหนดในลิงค์ลิสต์แบบสองทิศทาง
o การลบโหนดระหว่างข้อมูลที่มีอยู่ในลิงค์ลิสต์ทิศทางเดียว
 curr อ้างอิงตาแหน่งโหนดทีต่ อ้ งการลบข้อมูล
 prev1 อ้างอิงโหนดก่อนหน้าทีจ่ ะทาการลบข้อมูล
 prev2 อ้างอิงโหนดถัดไปของโหนดทีจ่ ะทาการลบ
36
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การลบโหนดในลิงค์ลิสต์แบบสองทิศทาง
o การลบโหนดระหว่างข้อมูลที่มีอยู่ในลิงค์ลิสต์ทิศทางเดียว
1. เปลีย่ นการอ้างอิง next ของโหนดทีอ่ า้ งอิงด้วยตัวแปร prev1 ให้มคี ่าเท่ากับการอ้างอิง
next ของตัวแปร curr โดยแสดงการกาหนดการทางานได้ดงั นี้
Java
C
prev1.setNext(curr.getNext()); prev1->next = curr->next;
2. เปลีย่ นการอ้างอิง precede ของโหนดทีอ่ า้ งอิงด้วยตัวแปร prev2 ให้มคี า่ เท่ากับการ
อ้างอิง precede ของตัวแปร curr โดยแสดงการกาหนดการทางานและรูปการ
กาหนดการทางานได้ดงั นี้
Java
C
prev2.setPrecede(curr.getPrecede()); prev2->precede = curr->precede;
37
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การลบโหนดในลิงค์ลิสต์แบบสองทิศทาง
o การลบโหนดที่เป็ นส่วนหัวในลิงค์ลิสต์แบบสองทิศทาง
 prev1 ไม่อา้ งอิงโหนดใดๆ โดยมีคา่ เท่ากับ null
 curr อ้างอิงตาแหน่งโหนดทีต่ อ้ งการลบ
 prev2 อ้างอิงตาแหน่งโหนดก่อนหน้าทีต่ อ้ งการลบ
Java
1
2
head = prev2;
prev2.setPrecede = null;
C
head = prev2;
prev2->precede = NULL;
38
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การลบโหนดในลิงค์ลิสต์แบบสองทิศทาง
o การลบโหนดตาแหน่ งสุดท้ายของลิงค์ลิสต์แบบสองทิศทาง
 curr อ้างอิงตาแหน่งโหนดสุดท้าย
 prev1 อ้างอิงตาแหน่งโหนดก่อนหน้าโหนดสุดท้าย
 prev2 มีคา่ เท่ากับ null เนื่องจากตาแหน่งถัดไปของตัวแปร curr มีคา่ เท่ากับ null
Java
C
prev1.setNext = null;
prev1->next = NULL;
รอ
prev1.setNext(prev2);
รอ
prev1->next = prev2
39
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การเพิ่มโหนดในลิงค์ลิสต์แบบสองทิศทาง
• newNode
• curr
• prev1
อ้างอิงโหนดใหม่ทต่ี อ้ งการเพิม่ เข้าไปในลิงค์ลสิ ต์แบบสองทิศทาง
อ้างอิงโหนดถัดไปทีต่ อ้ งการเพิม่ โหนดในลิงค์ลสิ ต์
อ้างอิงโหนดก่อนหน้าทีต่ อ้ งการเพิม่ โหนดในลิงค์ลสิ ต์
o การเพิ่มโหนดรระหว่างข้อมูลที่มีอยู่ในลิงค์ลิสต์แบบสองทิศทาง
 curr อ้างอิงโหนดทีต่ อ้ งการเพิม่ โหนด
 prev1 อ้างอิงโหนดด้านหลังโหนดทีต่ อ้ งการเพิม่ โหนด
40
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การเพิ่มโหนดในลิงค์ลิสต์แบบสองทิศทาง
o การเพิ่มโหนดรระหว่างข้อมูลที่มีอยู่ในลิงค์ลิสต์แบบสองทิศทาง
1. กาหนดการเชือ่ มโยงโหนดถัดไป (next) กาหนดให้การอ้างอิง next ของ newNode มีค่าการอ้างอิง
เท่ากับการอ้างอิง next ของตัวแปร prev1 และกาหนดการอ้างอิง next ของ prev1 เท่ากับ newNode
Java
newNode.setNext(prev1.getNext());
prev1.setNext(newNode);
C
newNode->next = prev1->next;
prev1->next = newNode;
2. กาหนดการอ้างอิงย้อนกลับ (precede) โดยกาหนดให้การอ้างอิง precede ของ newNode มีค่าการ
อ้างอิงเท่ากับการอ้างอิง precede ของตัวแปร prev2 และกาหนดการอ้างอิง precede ของ prev2
เท่ากับ newNode ดังแสดงการกาหนดการทางานและรูปการทางานดังนี้
Java
C
newNode.setPrecede(curr.getPrecede()); newNode->precede = curr.precede;
curr->precede = newNode
curr.setPrecede(newNode);
41
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การเพิ่มโหนดในลิงค์ลิสต์แบบสองทิศทาง
o การเพิ่มโหนดในส่วนหัวของลิงค์ลิสต์แบบสองทิศทาง
 curr อ้างอิงโหนดทีต่ อ้ งการเพิม่ โหนด
 prev1 มีคา่ เท่ากับ null เนื่องจากเจอข้อมูลในตาแหน่งแรกจึงไม่อา้ งอิงโหนดใด
Java
1
2
3
newNode.setNext = curr;
curr.setPrecede = newNode;
head = newNode;
C
newNode->next = curr;
curr->precede = newNode;
head = newNode;
42
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การเพิ่มโหนดในลิงค์ลิสต์แบบสองทิศทาง
o การเพิ่มโหนดในตาแหน่ งสุดท้ายของลิงค์ลิสต์แบบสองทิศทาง
 curr มีคา่ เท่ากับ null เนื่องจากค้นหาข้อมูลไม่เจอในลิงค์ลสิ ต์
 prev1 อ้างอิงโหนดสุดท้ายในลิงค์ลสิ ต์
Java
1
2
prev1.setNext = newNode;
newNode.setPrecede = prev1;
C
prev1->next = newNode;
newNode->precede = prev1;
43
การจัดการลิงค์ลสิ ต์แบบสองทิศทาง
การเปลี่ยนแปลงโครงสร้างที่ในลิงค์ลิสต์แบบทิศทาง
• สามารถนารูปแบบการเปลีย่ นแปลงโครงสร้างทีใ่ นลิงค์ลสิ ต์แบบทิศทางเดียว นามาเพิม่
ประสิทธิภาพให้กบั ลิงค์ลสิ ต์แบบสองทิศทางได้
44
การนาลิงค์ลสิ ต์ไปใช้งาน
• นาลิงค์ลสิ ต์ไปใช้ในการจัดเก็บข้อมูลการยืมแผ่นซีดภี าพยนตร์ในร้านเช่าแผ่นภาพยนตร์
• ประกอบด้วยโครงสร้างลิงค์ลสิ ต์ท่ที าหน้าที่เก็บข้อมูลแผ่นซีดภี าพยนตร์ (Inventory)
ซึง่ มีโครงสร้างลิงค์ลสิ ต์เก็บข้อมูลแผ่นซีดภี าพยนตร์
 title
 have
ทาหน้าทีเ่ ก็บข้อมูลเกีย่ วกับแผ่นซีดภี าพยนตร์
ทาหน้าทีเ่ ก็บจานวนแผ่นซีดภี าพยนตร์เรือ่ งนี้วา่ ภายในร้านมีจานวนกี่
แผ่น
 want
ทาหน้าทีเ่ ก็บจานวนความต้องการในการเช่าแผ่นซีดภี าพยนตร์เรือ่ งนี้ใน
กรณีทไ่ี ม่มแี ผ่นภาพยนตร์เรือ่ งนี้อยูใ่ นร้าน
 waitingList ทาหน้าทีเ่ ก็บการเชือ่ มโยงโหนดข้อมูลลูกค้าทีร่ อการยืมแผ่นซีดี
ภาพยนตร์เรือ่ งนี้
 next
ทาหน้าทีเ่ ชือ่ มไปยังโหนดภาพยนตร์เรือ่ งถัดไป
45
การนาลิงค์ลสิ ต์ไปใช้งาน
• ลิงค์ลสิ ต์เก็บข้อมูลลูกค้าทีร่ อการยมแผ่นซีดี โดยโครงสร้างลิงค์ลสิ ต์เก็บข้อมูลลูกค้าทีร่ อ
การยมแผ่นซีดี
 item ทาหน้าทีเ่ ก็บข้อมูลรายละเอียดเกีย่ วกับลูกค้าทีร่ อการยืมแผ่นซีดี เช่น ชือ่
โทรศัพท์ เป็ นต้น
 next ทาหน้าทีเ่ ชือ่ มไปยังโหนดถัดไปของลูกค้าทีร่ อการยืมแผนซีดหี นังเรือ่ งนี้
46
การนาลิงค์ลสิ ต์ไปใช้งาน
จะได้รปู แบบการเก็บข้อมูลแผ่นซีดภี าพยนตร์โครงสร้างลิงค์ลสิ ต์ดงั นี้
1. รายการเก็บข้อมูลภาพยนตร์ (Inventory List) เป็ นกลุ่มลิงค์ลสิ ต์เก็บข้อมูล แผ่นซีดี
ภาพยนตร์
2. รายการเก็บข้อมูลบุคคลที่รอการยืมแผ่นซีดี (Wait List) เป็ นกลุ่มลิงค์ลสิ ต์เก็บข้อมูล
ลูกค้าทีร่ อการยืมแผ่นซีดี
47
สรุปเนื้อหาบทที่ 4
• ลิงค์ลสิ ต์เป็ นรูปแบบการเก็บข้อมูลทีส่ ามารถเพิม่ และลดขนาดการเก็บข้ อมูลได้อตั โนมัติ
ตามความต้องการของผูใ้ ช้ ส่งผลทาให้การใช้งานหน่วยความมีประสิทธิภาพ
• ลิงค์ลสิ ต์ม ี 2 แบบ แยกตามรูปแบบการเชือ่ มโยงโหนดในลิงค์ลสิ ต์ คือ
o ลิงค์ลสิ ต์ทศิ ทางเดียวประกอบด้วยอย่างน้อย 2 ส่วนคือ ส่วนเก็บข้อมูล (item) และ
ส่วนเชื่อมโยง (next) เรียกทัง้ สองส่วนมารวมกันว่า โหนด (Node) และลิงค์ลสิ ต์ตอ้ ง
มีตวั แปรทาหน้าทีอ่ ้างอิงตาแหน่ งเริม่ ต้นของลิงค์ลสิ ต์ เพื่อใช้ เป็ นตาแหน่ งเริม่ ต้นใน
การท่องเข้าไปในลิงค์ลสิ ต์คอื head
o ลิงค์ลสิ ต์แบบสองทิศทางเป็ นรูปแบบลิงค์ลสิ ต์ทส่ี ามารถท่องไปและท่อ งกลับภายใน
ลิงค์ลสิ ต์ได้ โดยลิงค์ลสิ ต์แบบสองทิศทางมีสว่ นประกอบอย่างน้อย 3 ส่วนคือ ส่วน
เก็บข้อมูล (item) ส่วนเชื่อมโยงโหนดไปข้างหน้ า (next) และส่วนเชื่อมโยงข้าง
หลังเพื่อใช้ในการย้อนกลับ (precede)
48