Cấu tạo của DSLKQuả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” mà thôi Ta cũng có thể quản lý danh sách bằn
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
Trang 5Bài tập
Hãy cài đặt hàm (bằng ngôn ngữ C/C++) chèn một phần tử có giá trị x vào vị trí vt trong mảng số nguyên a, kích thước n, theo mẫu hàm như sau:
void ChenX(int a[], int &n, int x, int vt);
Trang 8Bài tập
Hãy cài đặt hàm (bằng ngôn ngữ C/C++) xóa phần tử có giá trị x (nếu có) trong mảng số nguyên a, kích thước n (giả sử giá trị các phần tử trong mảng không trùng nhau), theo mẫu hàm như sau:
void XoaX (int a[], int &n, int x);
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?
Trang 11Biến tĩnh và biến động trong C++
Biến tĩnh
<kiểu dữ liệu> tên biến;
Vd: int a; float y; char s[20];
Tồn tại trong phạm vi khai báo
Được cấp phát vùng nhớ trong vùng dữ liệu
Kích thước cố định
Trang 12Biến tĩnh và biến động trong C++
Biến động
<kiểu dữ liệu> *tên biến;
Vd: int *a; float *y;
Chứa địa chỉ của một đối tượng dữ liệu
Được cấp phát hoặc giải phóng bộ nhớ tùy
thuộc vào người lập trình
Kích thước có thể thay đổi
Trang 13Biến tĩnh và biến động trong C++
Trang 14Danh 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 16Đặ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 17Đặ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
Trang 18Cấu tạo của DSLK
pHead pTail
List
Trang 19Cấ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” mà thôi
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” mà thôi
Trang 20Cấu tạo của nút
Trang 21Thao 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 22Thao tác xóa node khỏi DSLK
Cần xóa
pHead pTail
List
Trang 23Cá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 24Cá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”
Trang 25Cá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 26Phải dịch chuyển các
phần tử khi Thêm/Xóa Chỉ cần thay đổi con trỏ liên kết khi Thêm/XóaTruy xuất ngẫu nhiên Truy xuất tuần tự
Trang 27DSLK đơn
Cấu trúc 1 node
Data pNext
pNext : Con trỏ đến node kế tiếp
pHead : Con trỏ đến node đầu pHead pTail
List
Trang 28Khai báo cấu trúc node
struct tNODE
{
<kiểu dữ liệu> Data ;
struct tNODE *pNext ;
};
Data
pNext
Trang 29Khai báo cấu trúc node lưu số nguyên
Trang 30Khai báo cấu trúc node lưu thông tin SV
typedef struct tSinhVien SINHVIEN;
Trang 31Khai báo cấu trúc DSLK đơn
Trang 32Khai báo cấu trúc DSLK đơn
struct tList
{ NODE *pHead, *pTail;};
struct tNODE
{
<kiểu dữ liệu> Data ;
struct tNODE *pNext ;
pHead pTail list
Trang 33Các thao tác trên DSLK đơn
Tạo lập danh sách rỗng
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 34Khai báo thư viện hàm
Khai báo thư viện hàm
1
Khai báo cấu trúc danh sách liên kết
Khai báo cấu trúc danh sách liên kết
2
Khai báo các nguyên mẫu hàm
Khai báo các nguyên mẫu hàm
3
void main() {
Tạo lập danh sách rỗng Nhập dữ liệu vào danh sách Các thao tác xử lý trên danh sách Hủy danh sách
}
void main() {
Tạo lập danh sách rỗng Nhập dữ liệu vào danh sách Các thao tác xử lý trên danh sách Hủy danh sách
}
4
Trang 35Tạo lập danh sách rỗng
void CreateEmptyList(LIST &list)
{
list.pHead = list.pTail = NULL;
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 36Kiểm tra danh sách rỗng
bool IsEmptyList(LIST list)
Trang 37Thêm một nút vào danh sách
Trang 38Thêm một nút vào danh sách
TH danh sách đã có phần tử
pHead pTail
pNew
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 39TH Thêm một nút vào đầu danh sách
pHead pTail
pNew
1 2
Trang 40TH Thêm một nút vào đầu danh sách
pHead pTail
Vẽ lại
Trang 41TH Thêm một nút vào đầu danh sách
Hãy vẽ lại “đường kết nối” theo
vào đầu danh sách
?
Trang 42TH Thêm một nút vào đầu danh sách
pNew->pNext = list.pHeadlist.pHead = pNew
1
2
Trang 43TH Thêm một nút vào đầu danh sách
Hãy viết hàm thêm phần tử pNew vào đầu danh sách (bằng ngôn ngữ C/C++), theo mẫu sau:
void AddHead(LIST &list, NODE *pNew)
?
Trang 44TH Thêm một nút vào cuối danh sách
Trang 45TH Thêm một nút vào cuối danh sách
Hãy vẽ lại “đường kết nối” theo
vào cuối danh sách
?
42
Trang 46TH Thêm một nút vào cuối danh sách
Hãy viết hàm thêm phần tử pNew vào cuối danh sách (bằng ngôn ngữ C/C++), theo mẫu sau:
void AddTail (LIST &list, NODE *pNew)
?
Trang 47Nhập dữ liệu vào danh sách
Nhập dữ liệu cho node
Tạo con trỏ node
Trang 48Nhậ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
Data
pNew
x pNew->Data = x
pNew->pNext = NULL
Trang 49Nhập dữ liệu vào danh sách
VD hàm tạo và trả về con trỏ node có chứa giá trị nguyên x bằng ngôn ngữ C++
NODE *CreateNode (int x)
Trang 50Nhập dữ liệu vào danh sách
VD hàm nhập dữ liệu cho danh sách số nguyên
và đưa vào đầu danh sách
void Input(LIST &list)
Trang 51Xuất dslk
pHead pTail
List
p
Trang 52Bài tập
Cài đặt các hàm sau trên dslk đơn số nguyên:
1 Đếm số lượng node trong dslk
int DemSL(LIST list);
void InChan(LIST list);
5 Tính giá trị trung bình cộng các node lẻ
Trang 53Chèn node vào DSLK đơn
Chèn vào sau node p
Chèn vào trước node p 25
pNew p
Trang 54Chèn node vào sau node p
pNew p
Trang 55Chèn node vào trước node p – Cách 1
pNew p
pPrev
Trang 56Chèn node vào trước node p – Cách 1
Hãy viết hàm tìm và trả về con trỏ node đứng trước con trỏ node p (bằng ngôn
ngữ C/C++), theo mẫu sau:
NODE *PrevNode (LIST list, NODE *p)
?
Trang 57Chèn node vào trước node p – Cách 2
pNew p
Bước 1 Chèn pNew vào sau p
Bước 2 Hoán vị giá trị pNew và p
Trang 58Xóa một nút trong danh sách
Xóa nút đầu của danh sách Ảnh hưởng
Trang 59Xóa một nút trong danh sách
Xóa nút đầu của danh sách
Trang 60Xóa một nút trong danh sách
Hãy viết hàm xóa nút đầu của danh sách (bằng ngôn ngữ C/C++), theo mẫu sau:
void DeleteHead (LIST &list)
(lưu ý trường hợp danh sách chỉ còn 1 node
trước khi xóa)
?
Trang 61Xóa một nút trong danh sách
Xóa nút cuối của danh sách
Trang 62Xóa một nút trong danh sách
Hãy viết hàm xóa nút cuối của danh sách (bằng ngôn ngữ C/C++), theo mẫu sau:
void DeleteTail (LIST &list)
(lưu ý trường hợp xóa danh sách chỉ có 1 node)
?
Trang 63Xóa một nút trong danh sách
Xóa nút giữa của danh sách
Trang 64Xóa một nút trong danh sách
Hãy viết hàm xóa một node bất kỳ trong danh sách (bằng ngôn ngữ C/C++),
theo mẫu sau:
void DeleteNode (LIST &list, NODE *pDel)
?
Trang 65Xóa một nút trong danh sách
Hãy viết hàm hủy toàn bộ danh sách
(bằng ngôn ngữ C/C++), theo mẫu sau:
void DestroyList (LIST &list)
?
Trang 666 Chèn node có giá trị x vào phía sau node có giá trị lớn nhất
void ChenXSauMax(LIST &list, int x);
7 Xóa node có giá trị x
bool XoaX(LIST &list, int x);
8 Sắp tăng dslk
void SapTang(LIST &list);