Bài giảng Cấu trúc dữ liệu và giải thuật - Chương 4: Danh sách liên kết cung cấp các kiến thức giúp sinh viên nắm vững khái niệm về kiểu dữ liệu tĩnh và động, nắm vững cách tổ chức dữ liệu động bằng danh sách liên kết và minh họa được các thao tác xử lý trên danh sách liên kết đơn, cài đặt minh họa được các thao tác của danh sách đơn bằng ngôn ngữ C#.
Trang 1Chương 4 Danh sách liên kết
(Phần 1 – 3 tiết)
Trần Minh Thái
Email: minhthai@huflit.edu.vn
Website: www.minhthai.edu.vn
Trang 2Mục tiêu
Nắm vững khái niệm về kiểu dữ liệu tĩnh và động
Nắm vững cách tổ chức dữ liệu động bằng danh sách liên kết và minh họa được các thao tác xử lý trên danh sách liên kết đơn
Cài đặt minh họa được các thao tác của danh sách đơn bằng ngôn ngữ C#
2
Trang 315 15
1 1
? Làm sao để chèn thêm số 6 vào vị trí 5 của mảng
6 6
Trang 415 15
1 1
6 6
Bổ sung thêm
Giả sử cần thêm tiếp 1 phần tử
?
Trang 5Bài tập
Hãy cài phương thức (bằng ngôn ngữ C#) chèn một phần tử có giá trị x vào vị trí
vt trong mảng số nguyên arr, theo mẫu như sau:
class CMyIntArray{
int []arr;
public void InsertX(int x, int vt){}
}
Trang 615 15
1 1
Trang 715 15
1 1
Trang 9Vấn đề kiểu dữ liệu tĩnh
Độ phức tạp của chèn/ xóa trên mảng 1 chiều là O(n)
i
Trang 10Vấn đề kiểu dữ liệu tĩnh
Giải quyết vấn đề phức tạp khi chèn/ xóa?
Giải quyết vấn đề giới hạn kích thước vùng nhớ tối đa?
Giải quyết vấn đề vùng nhớ không liên tục?
Giải quyết vấn đề giải phóng vùng nhớ khi không cần dùng đến?
10
DÙNG CẤU TRÚC DỮ LIỆU ĐỘNG
Trang 11Danh sách liên kết (DSLK)
1
7 2 6
3 10 8 5 9
Các phần tử kết dính với nhau bằng “sợi dây liên kết”
Trang 13Đặc điểm DSLK
Một dãy tuần tự các nút (Node)
Giữa hai nút có con trỏ liên kết
Các nút không cần phải lưu trữ liên tiếp nhau trong bộ nhớ
Có thể mở rộng tuỳ ý (chỉ giới hạn bởi dung lượng bộ nhớ)
Trang 14Đặc điểm DSLK
Thao tác Chèn/Xóa không cần phải dịch chuyển phần tử mà chỉ cần thay đổi mối liên kết
Quản lý phần tử đầu tiên bằng con trỏ pHead
Có thể truy xuất đến các phần tử khác thông qua con trỏ liên kết
14
Trang 15Cấu tạo của DSLK
pHead pTail List
Trang 16Cấu tạo của nút
Tạo lập bằng cách cấp phát bộ nhớ động
Mỗi nút có 2 thông tin:
Dữ liệu (data)
Con trỏ liên kết đến phần tử kế tiếp trong danh sách (Next pointer link)
Nếu không trỏ đến phần tử nào thì con trỏ Next = null
16
Trang 17Thao tác chèn thêm node vào DSLK
“Kết nối” lại sợi dây liên kết theo trình tự
pHead pTail List
Trang 18Thao tác xóa node khỏi DSLK
18
Cần xóa
pHead pTail List
Trang 19Các loại hình DSLK
DSLK đơn: Các phần tử kết nối với nhau theo hướng “chiều đi tới”
Trang 20Các loại hình DSLK
DSLK đôi: Các phần tử kết nối với nhau theo hướng “chiều đi tới và và đi lui”
20
Trang 21Các loại hình DSLK
Danh sách liên kết vòng: Các phần tử kết nối với nhau theo hướng “chiều đi tới”
và phần tử cuối cùng có “đường đi vòng trở lại tới” phần tử đầu danh sách
Trang 22So sánh Mảng và DSLK
Các phần tử lưu trữ tuần tự (địa chỉ tăng
Phải dịch chuyển các phần tử khi
Trang 23DSLK đơn
Cấu trúc 1 node
Data
pNext
Data : Dữ liệu của node
pNext : Con trỏ đến node kế tiếp
pHead : Con trỏ đến node đầu
pTail : Con trỏ đến node cuối
pHead pTail List
Trang 24Cấu tạo của DSLK
Quản lý toàn bộ danh sách liên kết thông qua con trỏ đầu pHead
pHead không phải là 1 nút, nó chỉ là “con trỏ chỉ đến nút”
Ta cũng có thể quản lý danh sách bằng cách sử dụng thêm con trỏ cuối (pTail)
pTail không phải là 1 nút, nó chỉ là “con trỏ chỉ đến nút”
24
Trang 25Cấu tạo của nút
Tạo lập bằng cách cấp phát bộ nhớ động
Mỗi nút có 2 thông tin:
Dữ liệu (data)
Con trỏ liên kết đến phần tử kế tiếp trong danh sách (Next pointer link)
Nếu không trỏ đến phần tử nào thì con trỏ Next = null
Trang 26Khai báo node
get { return data; }
set { data = value; }
}
public Node<T> PNext
{
get { return pNext; }
set { pNext = value; }
}
}
Trang 27Khai báo node lưu số nguyên 20
pNext
public class IntNode
{
private int data;
private IntNode pNext = null;
public int Data {
get { return data; } set { data = value; } }
public IntNode PNext {
get { return pNext; } set { pNext = value; }
Trang 28Tạo lập danh sách rỗng
28
Sau khi tạo lập
?pHead
?pTail List
Trước khi tạo lập
pHead pTail List
pHead và pTail chưa xác định pHead và pTail trỏ vào null (rỗng)
Trang 29Khai báo DSLK đơn
pHead pTail List
class CMyLinkedList<T>
{
private Node<T> pHead = null;
private Node<T> pTail = null;
Trang 30Khai báo DSLK đơn số nguyên
30
pHead pTail List
public class CMyIntLinkedList
{
private IntNode pHead = null;
private IntNode pTail = null;
//Các phương thức }
Trang 31Các thao tác trên DSLK đơn
Kiểm tra danh sách rỗng
Thêm 1 nút vào danh sách
Duyệt danh sách
Xóa 1 nút
Tìm 1 phần tử
Sắp xếp danh sách
Trang 32Kiểm tra danh sách rỗng
32
Danh sách rỗng
pHead pTail List
public bool IsEmpty()
{
return pHead == null;
}
Trang 33Thêm một nút vào danh sách
Trang 34Thêm một nút vào danh sách
Có 2 trường hợp để thêm pNew
1.Thêm pNew vào đầu (AddHead)
2.Thêm pNew vào cuối (AddTail)
Trang 35TH Thêm một nút vào đầu danh sách
pHead pTail
pNew
1 2
Trang 36TH Thêm một nút vào đầu danh sách
Trang 37TH Thêm một nút vào đầu danh sách
pHead pTail
Hãy vẽ lại “đường kết nối” theo
thứ tự thích hợp khi thêm pNew
vào đầu danh sách ?
Trang 38TH Thêm một nút vào đầu danh sách
38
1 pNew.PNext = pHead;
2 pHead = pNew;
Trang 39TH Thêm một nút vào đầu danh sách
Hãy viết phương thức thêm phần tử vào
đầu danh sách (C#), theo mẫu sau:
public void AddHead(Node<T> pNew)
?
Trang 40TH Thêm một nút vào cuối danh sách
1
1
2
2
Trang 41TH Thêm một nút vào cuối danh sách
pHead pTail
Hãy vẽ lại “đường kết nối” theo
thứ tự thích hợp khi thêm pNew
vào cuối danh sách ?
42
Trang 42TH Thêm một nút vào cuối danh sách
42
Hãy viết phương thức thêm phần tử pNew vào cuối danh sách (C#), theo mẫu:
public void AddTail(Node<T> pNew)
?
Trang 43Nhập dữ liệu vào DSLK
Nhập dữ liệu cho node
Tạo con trỏ node
Thêm node vào danh sách
Trang 44Nhập dữ liệu vào danh sách
Để tạo node mới từ dữ liệu x có sẵn
Đưa dữ liệu có giá trị x vào phần data
Con trỏ pNext trỏ đến null
Trang 45VD nhập dữ liệu vào DSLK số nguyên
Tạo và trả về Node có chứa giá trị x
public class IntNode
{
private int data;
private IntNode pNext = null;
Trang 46Console Write( "Nhap vao so nguyen duong (nhap -1 ket thuc): " );
int TryParse( Console ReadLine(), out x);
Trang 47Xuất dslk
pHead pTail List
p
Trang 50Chương trình mẫu
Minh hoạ thao tác nhập vào đầu và xuất DSLK số nguyên Chương trình gồm 3 lớp:
1 Lớp IntNode: cấu trúc dữ liệu Node
2 Lớp CMyIntLinkedList: cấu trúc DSLK đơn
3 Lớp Program: gọi thử nghiệm
50
Trang 51Lớp IntNode
public class IntNode
{
private int data;
private IntNode pNext = null ;
public int Data
{
get { return data; }
set { data = value ; }
}
public IntNode PNext
{
get { return pNext; }
set { pNext = value ; }
Trang 52Lớp CMyIntLinkedList
52
public class CMyIntLinkedList
{
private IntNode pHead = null ;
private IntNode pTail = null ;
Trang 53Console Write( "Nhap vao so nguyen duong (nhap -1 ket thuc): " );
int TryParse( Console ReadLine(), out x);
Trang 56Bài tập thực hành
Cài đặt lớp CMyLinkedList có kiểu dữ liệu chung gồm các chức năng:
1. Tạo node
2. Thêm node vào đầu DSLK
3. Thêm node vào cuối DSLK
4. Tìm node có giá trị x
Sử dụng lớp này cho trường hợp kiểu dữ liệu là số nguyên và thử nghiệm các chức năng: nhập, xuất, tìm kiếm
56