Danh sách liên kết là tập hợp các phần tử được nối kết với nhau theo trình tự tuyến tính và trên đó có các thao tác tìm kiếm ,thêm bớt loại bỏ ,sắp xếp …... :Các loại danh sách liên kết
Trang 1Chủ đề : DANH SÁCH LIÊN KẾT
GVHD: Thầy TRẦN HỮU QUỐC THƯ
Thực hiện : VÕ MINH THÔNG
HỒ THỊ HỒNG VÂN NGUYỄN TRẦN CẨM THÚY
Trang 2Danh sách liên kết là tập hợp các phần tử được nối
kết với nhau theo trình tự tuyến tính và trên đó có
các thao tác tìm kiếm ,thêm bớt loại bỏ ,sắp xếp …
Trang 3():Các loại danh sách liên kết :
Danh sách liên kết kép :
Mỗi phần tử liên kết với phần tử đứng trước và sau nó trong danh sách:
Danh sách liên kết đơn :
Mõi phần tử liên kết với một phần tử đứng trước nó trong danh sách:
Trang 5Cấu trúc dữ liệu của một phần tử trong danh sách đơn
Mỗi phần tử trong danh sách đơn là một cấu trúc chứa hai thông tin
-Thành phần dữ liệu : lưu trữ các thông tin về bản thân phần tử
-Thành phần mối liên kết : lưu trữ địa chỉ của thành
phần tử kết tiếp trong danh sách hoặc lưu trữ giá trị NULL nếu là phần tử cuối danh sách
Trang 6Bằng ngôn ngữ C++ ta có thể định nghĩa danh sách liên kết như sau :
struct Node {
int info;
Node *pNext;
};
Node * p;Node *pHead;
Mỗi phần tử trong danh sách là một biến động được cấp phát hay hủy bỏ theo yêu cầu Danh sách đơn liên kết các biến động này lại với nhau một cách linh động khi thay đổi số lượng các phần tử
Trang 7Nếu biết được địa chỉ của một phần tử đầu tiên trong danh sách đơn thì có thể dựa vào thông tin pNext của nó để truy xuất đến phần tử thứ hai trong danh xâu và lại dựa vào thông tin Next của phần tử thứ hai để truy xuất đến phần tử thứ 3 … Nghĩa là để quản lý một xâu đơn thì cần biết địa chỉ của đầu xâu thường một con trỏ Head sẽ được dùng để lưu địa chỉ phần tử đầu xâu ta gọi Head đầu xâu được
khai báo như sau
NODE*pHead;
Trang 8Về nguyên tắt quản lý thì chỉ cần biết phần tử đầu xâu pHead nhưng thực tế có nhiều trường hợp cần làm với phần tử cuối xâu và như vây để tránh phải xác định phần
tử cuối xâu bằng cách duyệt từ dầu xâu có thể sử dụng thêm một con trỏ pTail giữ địa chỉ phần tử cuối xâu qua
khai báo sau :
Trang 9Các thao tác với danh sách:
//khoi tao danh sach
void init_list(){
pHead = NULL;
}
//tao mot nut co gia tri la XNode * GetNode(int x){
Node * pNew = new Node;
pNew->info=x;
pNew->pNext=NULL;
return pNew;
}
Trang 10Thuật tóan :
Bước 1 :
Nếu danh sách rỗng thì
B1.1: pHead=pNewB1.2:pTail=pHead;
Ngược lại :
B2.1:pNew=pNext=pHeadB2.2 pHead =pNew
Trang 11Thêm một phần tử vào đầu danh sách:
Trang 12-Thuật tóan:
Bắt dầu
Nếu danh sách rỗng
B1.1 pHead=pNew B1.2 pTail = pHead Ngược lại ;
B2.1 pTail->pNext=pNew B2.2 pTail = pNew
Trang 13Thêm phần tử vào cuối danh sách :
Z
pTail pHead
-
//them mot phan tu vao cuoi danh sach
void add_last( int x)
pTail=pTail->pNext;
} pTail->pNext=pNew;
Trang 14-//them mot phan tu x vao sau phan tu y
void add( int x, int y)
{
Node * p= find(y);
if (p!=NULL) {
Trang 16A B X Y Z
-pTail pHead
//xoa vi tri dau cua danhsach
int del_first() {
if (pHead!=NULL) {
Trang 17Thuật toán
Nếu q!=NULL thì
B1 p=q->pNext // p là phần tử cần hủy
B2 nếu (p!=NULL) thì // q không phải là phần tử cuối xâu
B2.1 q->pNext=p->pNext // tách p ra khỏi xâu
B2.2 delete p // hủy biến động do p trỏ đến
Trang 18Xóa p sau một phần tử đứng sau phần tử q :
pTail
pq
pHead
//xoa sau phan tu x trong danh sach
int del( int x) {
Trang 19-Xoá phần tử cuối danh sách:
//xoa vi tri cuoi cua danh sach
int del_last() {
q=q->pNext;
delete q->pNext; q->pNext=NULL; }
}
return 0;
Trang 20Thuật tóan
Bước 1
Tìm phần tử p có khóa x ( một cách hình thức gọi info = x) và phần tử q đứng trước
Trang 21Xoá phần tử có giá trị x:
// xoa phan tu co gia tri la x
int del_X( int x) {
return 0;
Trang 22//tim phan tu co gia tri la x
Node * find( int x) {
cout<<p->info <<" ";
p=p->pNext;
Trang 23Là thao tác thực hiện khi sử lý các phần tử như
Đếm các phần tử của danh sách ;
Tìm tất cả các phần tử thỏa điều kiện
Lấy thông tin tổng hợp từ các phần tử của danh sách
Hủy toàn bộ danh sách ( và giải phóng bộ nhớ )
Để duyệt danh sách ( và sử lý từng phần tử ) thực hiện các thao tác như sau
Trang 24Thuật toán
Bước 1 p=pHead // cho p trỏ đến phần tử đầu danh sách
Bước 2 trong khi p!=NULL // chưa hết danh sách
B2.1 xử lý phần tử p B2.2 p=p->pNext // cho p trỏ tới phần tử kế
Riêng hủy tòan bộ danh sách có sự thay đổi trong thủ tục duyệt ( xử lý ) danh sách trên do có một thao tác hủy phần tử và khi đó phải cập nhật các liên kết liên quan
Bước 1 trong khi pHead!=NULL // chưa hết danh sách
Trang 25void process ( Node & )
{
Node * p;
p=pHead;
while ( p!=NULL) {
processNOde(p); // xu ly cu the tung ung dung
p=p->pNext;
} }
void remove (Node & ) {
Trang 26Một danh sách có thứ tự ( danh sách được sắp xếp )
khi các phần tử của nó được sắp xếp theo một thứ tự
nào đó dựa trên một trường khóa Để sắp xếp một
danh sách có thễ thực hiện một trong hai phương án
Trang 27vị giá trị của hai phần tử sẽ chiếm chi phí đáng kể làm cho thao tác sắp xếp chậm lại và như thế phương án không tận dụng các ưu điểm của xâu
Trang 28Ví dụ cài đặt thuật tóan sắp xếp chọn trực tiếp như sau
q=p->pNext;min=p;
while(q!=NULL) {
Trang 29PHƯƠNG ÁN 2
Khi thành phần dữ liện ( data info ) của phẩn tử trong xâu có kích thước lớn thì có thể dùng một cách khác đó là thay vì hoán đổi giá tri info ,ta sẽ tìm cách thay đổi trình tự móc nối của các phần tử để thiết lập được thứ tự mong muốn cách này chỉ cho phép thao tác trên các móc nối ( trường pNext) Tuy nhiên các thao tác trên các móc nối sẽ phức tạp hơn là thao tác trực tiếp trên dữ liệu và vì vậy nếu dữ liệu không
quá lớn thì nên chọn phương án một Một trong những cách thay đổi móc nối đơn gian nhất là tạo một danh sách mới từ danh sách củ và có thứ tự ( và hủy
danh sách củ)
Trang 30Ví dụ : dùng phương án 2 cho thuật toán chọnt trực tiếp giả sử danh sách mới sẽ được quản lý bằng con trỏ đầu xâu RESULTthực hiện như sau
B 1 Khởi tạo danh danh sách mới result là rỗng
B 2 Tìm danh sác củ 1 phần tử nhỏ nhất quản lý bởi con trỏ min
B 3 Tách min khoi danh sach
B 4 Chèn min vào cuối danh sách result
B 5 Lặp lại bước 2 khi chưa hêt danh sách