1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Bài giảng cấu trúc dữ liệu và giải thuật – bài 15 danh sách liên kết

70 9 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 70
Dung lượng 1,06 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Các thao tác cơ bản của danh sách liên kết đơn.. Các thao tác cơ bản của danh sách liên kết vòng.. Danh sách liên k ết đơn 3/23 Để quản lý danh sách liên kết, thông thường cần: • Start

Trang 1

Gi ảng viên: TS Ngo Huu Phuc

Tel: 0438 326 077 Mob: 098 5696 580

Bài 15 Danh sách liên k ết

Trang 2

Bài 15: Danh sách liên k ết

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.

Tham kh ảo:

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

15.1 Gi ới thiệu chung (1/2)

 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.

dư thừa bộ nhớ xuất hiện

Trang 4

15.1 Gi ới thiệu chung (2/2)

 Để 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

15.2 Danh sách liên k ết đơn (1/23)

 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 kép.

Trang 6

15.2 Danh sách liên k ết đơn (2/23)

Trang 7

15.2 Danh sách liên k ết đơn (3/23)

 Để 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.

Trang 8

15.2 Danh sách liên k ết đơn (4/23)

Khai báo c ấu trúc một Node của danh sách:

template < class ListEntry>

struct node {

Trang 9

15.2 Danh sách liên k ết đơn (5/23)

15.2.2 Các thao tác cơ bản của danh sách liên kết đơn

Trang 10

15.2 Danh sách liên k ết đơn (6/23)

class 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 11

15.2 Danh sách liên k ết đơn (7/23)

Kh ởi tạo danh sách:

template < class ListEntry>

Trang 12

15.2 Danh sách liên k ết đơn (8/23)

Thê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

Trang 13

15.2 Danh sách liên k ết đơn (9/23)

Thêm m ột node đầu danh sách:

template<classListEntry>

intLList<ListEntry>::LAdd(ListEntry entry) {

malloc(sizeof(node<ListEntry>));

if(temp==NULL) {printf("Loi cap phat bo nho!\n");

return kt; }kt=1;

Trang 14

15.2 Danh sách liên k ết đơn (10/23)

Chè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

Trang 15

15.2 Danh sách liên k ết đơn (11/23)

Chè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!");

if(temp1==NULL) {printf("Loi cap phat bo nho!\n");

return kt; }kt=1;

temp1->data=entry;

temp1->link=temp->link;

temp->link=temp1;

}}

return kt; }

Trang 16

15.2 Danh sách liên k ết đơn (12/23)

Thê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

Trang 17

15.2 Danh sách liên k ết đơn (13/23)

Thêm m ột node cuối danh sách:

template<classListEntry>

intLList<ListEntry>::LAppend(ListEntry entry) {

while(temp->link!=NULL)temp=temp->link;

temp->data=entry;

temp->link=NULL; }

returnkt;

Trang 18

15.2 Danh sách liên k ết đơn (14/23)

Tì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

Trang 19

15.2 Danh sách liên k ết đơn (15/23)

Tìm m ột node trong danh sách:

template < class ListEntry>

int LList<ListEntry>::LFind(ListEntry value) {

Trang 20

15.2 Danh sách liên k ết đơn (16/23)

Xó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

Trang 21

15.2 Danh sách liên k ết đơn (17/23)

Xóa một node trong danh sách :

intLList<ListEntry>::LDelete(ListEntry value) {

node<ListEntry> *prev, *curr;

break; }

else {prev=curr;

free(curr); }

else {prev->link=curr->link;

free(curr);

}}}

returnkt;

}

Trang 22

15.2 Danh sách liên k ết đơn (18/23)

L ấy thông tin một node ở vị trí nào đó:

 S ử dụng con trỏ temp để duyệt qua

danh sách.

 Duy ệt cho đến khi đến node thứ pos,

l ấy thông tin tại node đó và trả lại cho

Cho trước pos = 3

Trang 23

15.2 Danh sách liên k ết đơn (19/23)

L ấy thông tin một node ở vị trí nào đó :

template <classListEntry>

int LList<ListEntry>::LGet(intpos, ListEntry *value) {

15.2.2 Các thao tác cơ bản của danh sách liên kết đơn

Trang 24

15.2 Danh sách liên k ết đơn (20/23)

Xác định số phần tử trong danh sách:

 S ử dụng con trỏ temp để duyệt qua

danh sách, cho đến khi temp =NULL.

Trang 25

15.2 Danh sách liên k ết đơn (21/23)

Trang 26

15.2 Danh sách liên k ết đơn (22/23)

Làm r ỗng danh sách:

 Xóa t ừng phần tử trong danh sách.

 S ử dụng con trỏ temp để xác định

ph ần tử cần xóa (từ đầu danh sách).

 D ịch chuyển con trỏ start sang ph ần

t ử kế tiếp.

 Thu h ồi ô nhớ ứng với con trỏ temp

 Th ực hiện cho đến khi start =NULL.

15.2.2 Các thao tác cơ bản của danh sách liên kết đơn

Trang 27

15.2 Danh sách liên k ết đơn (23/23)

Làm r ỗng danh sách :

template < class ListEntry>

void LList<ListEntry>::LMakeEmpty() {

node<ListEntry> *temp;

while (start!=NULL) {

temp=start;

start=start->link;

free(temp);

} }

15.2.2 Các thao tác cơ bản của danh sách liên kết đơn

Trang 28

15.3 Danh sách liên k ết vòng (1/20)

vào ph ần tử đầu tiên

Trang 29

15.3 Danh sách liên k ết vòng (2/20)

Start là con tr ỏ chỉ đến một phần tử 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 phần tử do start qu ản lý.

• Như vậy, từ bất kỳ vị trí nào trong danh sách cũng có thể duyệt hết danh sách.

Lưu ý : khi thêm hay b ớt phần tử nào trong danh sách cần đảm bảo rằng sau thao tác đó vẫn giữ được tính liên kết vòng.

15.3.1 Khái ni ệm về danh sách liên kết vòng

Trang 30

15.3 Danh sách liên k ết vòng (3/20)

template <class ListEntry>

class CLList {

public:CLList();

int CLAdd(ListEntry entry);

int CLInsert(ListEntry value, ListEntry entry);

int CLAppend(ListEntry entry);

int CLFind(ListEntry value);

int CLDelete(ListEntry value);

int CLLength();

void CLMakeEmpty();

int CGet(int pos, ListEntry *value);

template<typename ListEntry> friend void LPrint(CLList<ListEntry> list);

private:

15.3.2 Các thao tác cơ bản của danh sách liên kết vòng

Trang 31

15.3 Danh sách liên k ết vòng (4/20)

Kh ởi tạo danh sách LKV:

template < class ListEntry>

Trang 32

 N ếu danh sách không rỗng:

 S ử dụng biến temp để duyệt qua danh

sách, khi temp →link <> start

 C ấp phát ô nhớ cho temp →link

 Ph ần liên kết của ô nhớ mới trỏ vào

start

Start tr ỏ vào vùng ô nhớ mới trên.

15.3.2 Các thao tác cơ bản của danh sách liên kết vòng

Trang 33

15.3 Danh sách liên k ết vòng (6/20)

Thêm m ột node đầu danh sách LKV:

template< classListEntry>

intCLList<ListEntry>::CLAdd(ListEntry entry)

while (temp->link!=start)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;

Trang 34

15.3 Danh sách liên k ết vòng (7/20)

Chèn 1 node vào danh sách LKV:

 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.3.2 Các thao tác cơ bản của danh sách liên kết vòng

Trang 35

15.3 Danh sách liên k ết vòng (8/20)

Chèn 1 node vào danh sách LKV :

template<classListEntry>

intCLList<ListEntry>::CLInsert(ListEntry value,

ListEntry entry) {

int kt=0;

node<ListEntry> *temp, *temp1;

if(start==NULL) printf("Danh sach rong!");

temp1->data=entry;

temp1->link=temp->link;

temp->link=temp1;

}}

return kt;

}

Trang 36

 N ếu danh sách không rỗng:

 S ử dụng biến temp để duyệt qua danh

sách, khi temp →link <> start

 C ấp phát ô nhớ cho temp →link

 Ph ần liên kết của ô nhớ mới trỏ vào

Trang 37

15.3 Danh sách liên k ết vòng (10/20)

Thêm m ột node cuối danh sách LKV:

template<classListEntry>

intCLList<ListEntry>::CLAppend(ListEntry entry) {

while (temp->link!=start)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;

Trang 38

15.3 Danh sách liên k ết vòng (11/20)

Tìm m ột node trong danh sách LKV:

 S ử dụng con trỏ temp để duyệt qua

danh sách, khi temp →link <> start

 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.3.2 Các thao tác cơ bản của danh sách liên kết vòng

Trang 39

15.3 Danh sách liên k ết vòng (12/20)

Tìm m ột node trong danh sách LKV:

template < class ListEntry>

int CLList<ListEntry>::CLFind(ListEntry value) {

int pos=0;

node<ListEntry> *temp=start;

if (temp!=NULL) {

do { pos++;

if (temp->data==value) break ; temp=temp->link;

Trang 40

15.3 Danh sách liên k ết vòng (13/20)

Xóa m ột node trong danh sách LKV:

 Sử dụng 2 con trỏ prevcurr để 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=curr->link, danh sách có 1 phần

tử, cho start trỏ NULL, giải phóng ô nhớ

 Nếu curr <> start, cho prev->link trỏ vào

curr->link và giải phóng ô nhớ của curr

 Nếu curr=start, thay đổi start, prev->link

trỏ curr->link và giải phóng ô nhớ của curr

15.3.2 Các thao tác cơ bản của danh sách liên kết vòng

Trang 41

15.3 Danh sách liên k ết vòng (14/20)

Xóa một node trong danh sách LKV:

template<classListEntry>

intCLList<ListEntry>::CLDelete(ListEntry value) {

node<ListEntry> *prev, *curr;

else {prev=curr;

curr=curr->link; }}

else {prev=start; curr=start->link;

while (curr!=start) {prev=curr;

curr=curr->link; }prev->link=curr->link;

start=prev->link;

free(curr);

}}}}

return kt;

}

Trang 42

15.3 Danh sách liên k ết vòng (15/20)

L ấy thông tin một node ở vị trí nào đó LKV:

 S ử dụng con trỏ temp để duyệt qua danh

sách.

 Duy ệt cho đến khi đến node thứ pos , l ấy

thông tin t ại node đó và trả lại cho nơi gọi

hàm.

15.3.2 Các thao tác cơ bản của danh sách liên kết vòng

Cho trước pos = 3

Trang 43

15.3 Danh sách liên k ết vòng (16/20)

L ấy thông tin một node ở vị trí nào đó :

template<classListEntry>

intCLList<ListEntry>::CGet(intpos, ListEntry *value)

else

return0;

}

Trang 44

15.3 Danh sách liên k ết vòng (17/20)

Xác định số phần tử trong danh sách:

 S ử dụng con trỏ temp để duyệt qua

danh sách, khi temp<> start

Trang 45

15.3 Danh sách liên k ết vòng (18/20)

Xác định số phần tử trong danh sách LKV:

template < class ListEntry>

int CLList<ListEntry>::CLLength() { int length=0;

Trang 46

 Lưu ý: tính vòng của danh sách.

15.3.2 Các thao tác cơ bản của danh sách liên kết vòng

start temp

data link

Trang 47

15.3 Danh sách liên k ết vòng (20/20)

Làm r ỗng danh sách LKV:

template < class ListEntry>

void CLList<ListEntry>::CLMakeEmpty() {

node<ListEntry> *temp;

while (start!=NULL) {

temp=start;

start=start->link;

CLDelete(temp->data);

} }

15.3.2 Các thao tác cơ bản của danh sách liên kết vòng

Trang 48

15.4 Danh sách liên k ết kép (1/22)

 V ới danh sách liên kết đơn, chỉ cho phép duyệt danh sách theo một

chi ều.

 Để xóa một node cần lưu node đứng trước đó

 N ếu một liên kết bị hỏng, các phần tử sau đó không dùng được.

k ết như vậy, danh sách liên kết được gọi là có liên k ết kép

Trang 49

15.4 Danh sách liên k ết kép (2/22)

Start là con tr ỏ chỉ đến phần tử đầu tiên của danh sách liên kết kép.

End là con tr ỏ chỉ đến phần tử cuối cùng của danh sách liên kết kép.

• Thông thường, phần tử cuối có liên kết right trỏ tới NULL.

• B ằng cách sử dụng hợp lý liên kết left hay right, có thể đi về trước hay sau.

Lưu ý : khi thêm hay b ớt phần tử nào trong danh sách cần đảm bảo rằng sau thao tác đó vẫn giữ được tính liên kết vòng.

15.4.1 Khái ni ệm về danh sách liên kết kép

Trang 51

15.4 Danh sách liên k ết kép (4/22)

Khai báo c ấu trúc một Node của danh sách liên kết kép:

template < class ListEntry>

struct dnode {

Trang 52

15.4 Danh sách liên k ết kép (5/22)

template <class ListEntry>

class DLList {

public:DLList();

int DLAdd(ListEntry entry);

int DLInsert(ListEntry value, ListEntry entry);

int DLAppend(ListEntry entry);

int DLFind(ListEntry value);

int DLDelete(ListEntry value);

int DLLength();

void DLMakeEmpty();

int DGet(int pos, ListEntry *value);

template<typename ListEntry> friend void LPrint(DLList<ListEntry> list);

private:

15.4.2 Các thao tác cơ bản của danh sách liên kết kép

Trang 53

15.4 Danh sách liên k ết kép (6/22)

Kh ởi tạo danh sách LK kép:

template < class ListEntry>

Trang 54

15.4 Danh sách liên k ết kép (7/22)

Thêm m ột node đầu danh sách LK kép:

 N ếu danh sách rỗng, cấp phát ô nhớ và

cho startend tr ỏ vào ô nhớ đó.

 N ếu danh sách không rỗng:

 C ấp phát ô nhớ cho con trỏ temp

 T ạo các liên kết leftright tương ứng

(liên k ết temp->left tr ỏ vào NULL, liên

k ết temp->right tr ỏ vào start ).

Start tr ỏ vào vùng ô nhớ mới trên.

15.4.2 Các thao tác cơ bản của danh sách liên kết kép

1

2

start

data right left

1

2 3 4

Ngày đăng: 26/12/2021, 17:19

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w