Các thao tác cơ bản của danh sách liên kết đơn. start[r]
Trang 1Gi ảng viên: TS Ngo Huu Phuc
Tel: 0438 326 077 Mob: 098 5696 580 Email: ngohuuphuc76@gmail.com
Bài 15 Danh sách liên k ết
Trang 2N ội dung:
15.1 Gi ới thiệu chung.
15.2 Danh sách liên k ết đơn.
15.2.1 Khái ni ệm về danh sách liên kết đơn.
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn.
15.3 Danh sách liên k ết vòng.
15.3.1 Khái ni ệm về danh sách liên kết vòng.
15.3.2 Các thao tác cơ bản của danh sách liên kết vòng.
15.4 Danh sách liên k ết kép.
15.4.1 Khái ni ệm về danh sách liên kết kép.
15.4.2 Các thao tác cơ bản của danh sách liên kết kép.
15.5 M ột số ví dụ về danh sách liên kết.
1. Deshpande Kakde: C and Data structures.chm, Chapter 20: Linked Lists
2. Elliz Horowitz – Fundamentals of Data Structures.chm, Chapter 4: Linked Lists
3. Kyle Loudon: Mastering Algorithms with C.chm, Chapter 5 Linked Lists
4. Bài giảng TS Nguyễn Nam Hồng
Trang 3 V ới CTDL dạng mảng, bộ nhớ được sử dụng là m ột dãy liền
k ề và có kích thước cố định
Tuy nhiên, CTDL này có m ột số nhược điểm:
Th ời gian cho việc thêm hay b ớt phần tử trong mảng khá lâu vì
ph ải thay đổi cả các phần tử còn lại trong mảng.
Ngay c ả khi khai báo một lượng lớn các phần tử cho mảng để có
th ể áp dụng được cho nhiều bài toán, chúng ta cũng thấy khả năng
dư thừa bộ nhớ xuất hiện
Trang 4 Để khắc phục nhược điểm trên, có thể s ử dụng danh sách liên
k ết như là cấu trúc dữ liệu thay thế
Trong c ấu trúc này, không c ần xác định kích thước cho các
ph ần tử trước
Ta có th ể định nghĩa phần tử bất cứ lúc nào , sau đó liên kết
ph ần tử đó với danh sách đã có trước đó
Như vậy, mỗi phần tử sẽ bao gồm thông tin cần lưu trữ và liên
k ết với các phần tử khác.
Trang 5 Trong r ất nhiều trường hợp cần sử dụng đến danh sách liên kết động, danh sách liên kết động cần dùng đến khi kích thước danh sách chưa biết tại thời điểm biên dịch chương trình
Khi đó, danh sách có thể mở rộng hoặc thu hẹp lại tại thời
điểm chạy chương trình
C ấu trúc dữ liệu linked list s ử dụng mô hình liên kết động.
M ột số dạng của danh sách liên kết:
Danh sách liên k ết đơn.
Danh sách liên k ết vòng.
Danh sách liên k ết kép.
Trang 6 Danh sách liên k ết đơn là một
c ấu trúc dữ liệu bao gồm một tập
các nút, mà m ỗi nút bao gồm:
D ữ liệu cần lưu trữ
Liên k ết đến nút tiếp theo
Link
Data
Node
Add
60
1000
800
90
15.2.1 Khái ni ệm về danh sách liên kết đơn
Trang 7 Để quản lý danh sách liên kết, thông thường cần:
• Start là con tr ỏ chỉ đến phần tử đầu tiên của danh sách liên kết.
• Ph ần tử cuối của danh sách liên kết với vùng liên kết có nội dung NULL.
60
1000
800
90
15.2.1 Khái ni ệm về danh sách liên kết đơn
start
Trang 8Khai báo c ấu trúc một Node của danh sách:
template < class ListEntry>
struct node {
ListEntry data;
struct node *link;
};
15.2.1 Khái ni ệm về danh sách liên kết đơn
Trang 91 Kh ởi tạo danh sách.
2 LAdd: Thêm m ột node vào đầu danh sách.
3 LInsert: Chèn m ột node vào danh sách.
4 LAppend: Thêm m ột node vào cuối danh sách.
5 LFind: Tìm m ột node trong danh sách.
6 LDelete: Xóa m ột node trong danh sách.
7 LLength: S ố phần tử trong danh sách.
8 LMakeEmpty: Làm r ỗng danh sách.
9 LGet: L ấy thông tin về một phần tử trong danh sách.
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
Trang 10class LList {
public: LList();
int LAdd(ListEntry entry);
int LInsert(ListEntry value, ListEntry entry);
int LAppend(ListEntry entry);
int LFind(ListEntry value);
int LDelete(ListEntry value);
int LLength();
void LMakeEmpty();
int LGet(int pos, ListEntry *value);
template<typename ListEntry> friend void LPrint(LList<ListEntry> list);
private: node<ListEntry> *start;
};
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
Trang 11Kh ởi tạo danh sách:
template < class ListEntry>
LList<ListEntry>::LList()
{
start = NULL;
}
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
start
NULL
Trang 12Thêm m ột node đầu danh sách:
N ếu danh sách rỗng, cấp phát ô nhớ và
cho start tr ỏ vào ô nhớ đó.
N ếu danh sách không rỗng:
C ấp phát ô nhớ cho biến temp.
Ph ần liên kết của temp trỏ vào đầu danh
sách.
Con tr ỏ start trỏ vào temp.
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
start
NULL
data link
2
start
NULL
data link
temp
data link
Trang 13Thêm m ột node đầu danh sách:
template<classListEntry>
intLList<ListEntry>::LAdd(ListEntry entry) {
int kt=0;
node<ListEntry> *temp;
if(start==NULL) {
start=(node<ListEntry> *)
malloc(sizeof(node<ListEntry>));
if(start==NULL) {
printf("Loi cap phat bo nho!\n");
returnkt; } kt=1;
start->data=entry;
start->link=NULL;
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
else { temp=(node<ListEntry> *)
malloc(sizeof(node<ListEntry>));
if(temp==NULL) { printf("Loi cap phat bo nho!\n");
return kt; } kt=1;
temp->data=entry;
temp->link=start;
start=temp;
}
return kt;
Trang 14Chèn 1 node vào danh sách:
Nh ập thông tin về node đứng trước node thêm mới.
S ử dụng con trỏ temp để đến được node đứng trước đó.
C ấp phát ô nhớ cho biến temp1.
Ph ần liên kết của temp1 trỏ vào phần liên kết của con trỏ temp.
Ph ần liên kết của con trỏ temp trỏ vào temp1.
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
start
NULL
temp
data link
data link data link data link
data link
Trang 15Chèn 1 node vào danh sách :
template<classListEntry>
intLList<ListEntry>::LInsert(ListEntry value,
ListEntry entry) {
int kt=0;
node<ListEntry> *temp, *temp1;
if(start==NULL) printf("Danh sach rong!");
else {
temp=start;
while(temp!=NULL) {
if(temp->data==value)
break;
else
temp=temp->link;
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
if(temp!=NULL) { temp1=(node<ListEntry> *) malloc(sizeof(node<ListEntry>));
if(temp1==NULL) { printf("Loi cap phat bo nho!\n");
return kt; } kt=1;
temp1->data=entry;
temp1->link=temp->link;
temp->link=temp1;
} }
Trang 16Thêm m ột node cuối danh sách:
N ếu danh sách rỗng, cấp phát ô nhớ và
cho start tr ỏ vào ô nhớ đó.
N ếu danh sách không rỗng:
S ử dụng con trỏ temp đi đến cuối danh
sách.
C ấp phát ô nhớ cho temp->link.
Ph ần liên kết của temp->link trỏ vào
NULL.
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
start
NULL
data link
2
start
NULL
temp
data link
data link data link
1 data link 2
Trang 17Thêm m ột node cuối danh sách:
template<classListEntry>
intLList<ListEntry>::LAppend(ListEntry entry) {
int kt=0;
node<ListEntry> *temp;
if(start==NULL) {
start=(node<ListEntry> *)
malloc(sizeof(node<ListEntry>));
if(start==NULL) {
printf("Loi cap phat bo nho!\n");
returnkt; } kt=1;
start->data=entry;
start->link=NULL;
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
else { temp=start;
while(temp->link!=NULL) temp=temp->link;
temp->link=(node<ListEntry> *)
malloc(sizeof(node<ListEntry>));
if(temp->link==NULL) {
printf("Loi cap phat bo nho!\n");
returnkt; } kt=1; temp=temp->link;
temp->data=entry;
temp->link=NULL; }
Trang 18Tìm m ột node trong danh sách:
S ử dụng con trỏ temp để duyệt qua
danh sách.
S ử dụng thêm biến pos để lưu vị trí
c ủa node trong danh sách Nếu danh
sách r ỗng hoặc không tìm thấy trả về
0, ngược lại trả về vị trí của node.
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
start
NULL
temp
data link
data link data link data link
pos = 3
Trang 19Tìm m ột node trong danh sách:
template < class ListEntry>
int LList<ListEntry>::LFind(ListEntry value) {
int pos=0;
node<ListEntry> *temp=start;
while (temp!=NULL) {
pos++;
if (temp->data==value) break ;
temp=temp->link;
}
if (temp!=NULL)
return pos;
else return 0;
}
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
Trang 20Xóa m ột node trong danh sách:
S ử dụng 2 con trỏ prev và curr để tìm
node c ần xóa Con trỏ prev trỏ vào node
trước node cần xóa Con trỏ curr trỏ vào
node c ần xóa.
N ếu curr = start, cho start trỏ vào
start->link và gi ải phóng ô nhớ của curr.
N ếu không, prev->link trỏ tới
curr->link và gi ải phóng ô nhớ của curr.
15.2.2 Các thao tác cơ bản của danh sách liên kết đơn
1
2
start
NULL
curr
data link
data link data link data link
prev
start
NULL
curr
data link
data link
prev
NULL