KhoaCôngnghệthôngtin - fit.mta.edu.vnfit.mta.edu.vn/files/DanhSach/Lecture 07 - Danh sach lien...

Preview:

Citation preview

DANH SÁCH LIÊN KẾT

� Ngô Thành Long

� Khoa Công nghệ thông tin

� Học viện Kỹ thuật Quân sự

� 236 – Hoàng Quốc Việt – Hà Nội

Lecture 12 – Linked Lists

12.1. Khái niệm về danh sách

12.2. Các phép toán trên danh sách

12.3. Cài đặt danh sách sử dụng mảng

12.4. Danh sách liên kết đơn

12.5. Danh sách liên kết dạng vòng

12.6. Danh sách liên kết kép

12.7. Ứng dụng của danh sách liên kết

12.8. Bài tập thực hành

24/09/20132

Lecture 12 – Linked Lists

12.1. Kh12.1. Kháái nii niệệm vm vềề danh sdanh sááchch

12.2. Các phép toán trên danh sách

12.3. Cài đặt danh sách sử dụng mảng

12.4. Danh sách liên kết đơn

12.5. Danh sách liên kết dạng vòng

12.6. Danh sách liên kết kép

12.7. Ứng dụng của danh sách liên kết

12.8. Bài tập thực hành

24/09/20133

� Thực chất, mô hình toán học của danh sách là một tập hợp hữu hạn các phần tử có cùng một kiểu với khả năng nhập xuất dữ liệu rộng hơn cấu trúc dữ liệu kiểu ngăn xếp hay hàng đợi.

12.1. Khái niệm về danh s ách(list)

Ngăn xếp

Hàng đợiNhập

Lấy ra

Danh sách (list)

List

24/09/20134

12.1. Khái niệm về danh s ách(list)

�� CCàài đi đặặt: t:

� Ta có thể biểu diễn danh sách như là một chuỗi các phần tửcủa nó: a1, a2, . . ., an với n ≥ 0.

� Nếu n=0 ta nói danh sách rỗng (empty list).

� Nếu n > 0 ta gọi a1 là phần tử đầu tiên (firstfirst) và an là phần tử cuối cùng (lastlast) của danh sách.

� Tuy nhiên, cách biểu diễn này tồn tại nhiều hạn chế.

24/09/20135

Lecture 12 – Linked Lists

12.1. Khái niệm về danh sách

12.2. C12.2. Cáác phc phéép top toáán trên danh sn trên danh sááchch

12.3. Cài đặt danh sách sử dụng mảng

12.4. Danh sách liên kết đơn

12.5. Danh sách liên kết dạng vòng

12.6. Danh sách liên kết kép

12.7. Ứng dụng của danh sách liên kết

12.8. Bài tập thực hành

24/09/20136

12.2. Các ph ép to án trên danh s ách

� Các phép toán cơ bản trên danh sách:

� insertToList(list, position, value): thêm một phần tử vào một vị trí trên danh sách;

� deleteFromList(list, position): xóa phần tử từ vị trí cho trước trên danh sách;

� makeEmptyList(list): làm rỗng hoặc khởi tạo danh sách;

24/09/20137

12.2. Các ph ép to án trên danh s ách

�� CCáác hc hààm bm bổổ trtrợợ::

� isEmptyList(list) : kiểm tra danh sách rỗng;

� searchList(list, value): định vị phần tử có nội dung value đầu tiên trong danh sách list;

� printList(list): in ra danh sách;

� sortList(list): sắp xếp danh sách;

�� ChChúú ý: ý: tùy thuộc vào kiểu cài đặt danh sách, có thể xây dựng những hàm và phép toán khác.

24/09/20138

Lecture 12 – Linked Lists

12.1. Khái niệm về danh sách

12.2. Các phép toán trên danh sách

12.3. C12.3. Càài đi đặặt danh st danh sáách sch sửử ddụụng mng mảảngng

12.4. Danh sách liên kết đơn

12.5. Danh sách liên kết dạng vòng

12.6. Danh sách liên kết kép

12.7. Ứng dụng của danh sách liên kết

12.8. Bài tập thực hành

24/09/20139

� Khai báo (trên ngôn ngữ C) danh sách sử dụng mảng:

#define MAXSIZE 100 // Khai báo kích cỡ tối đa của ds sẽ sử dụng;typedef int ElementType; // Khai báo kiểu dữ liệu dùng cho ds;typedef struct{

ElementType Elements[MAXSIZE]; // sử dụng mảng để quản lý ds;int last; // biến để quản lý số phần tử của ds;

}SingleList;...SingleList list;

12.3. Cài đặt danh s ách sử dụng mảng

0 MAXSIZE - 1

first = 0 last

24/09/201310

� Một số thao tác cần cài đặt khi làm việc với danh sách:

� void insertToList(SingleList *list, int position, ElementType value);

� void deleteFromList(SingleList *list, int position);

� void makeEmptyList(SingleList *list);

� int isEmptyList(SingleList *list);

� int isFullList(SingleList *list);

12.3. Cài đặt danh s ách sử dụng mảng

0 MAXSIZE - 1

first = 0 last

24/09/201311

�� KhKhởởi ti tạạo danh so danh sáách:ch: makeEmptyList(SingleList *list):

Biến đếm last nhận giá trị ngoài khoảng [0, MAXSIZE-1];

�� KiKiểểm tra danh sm tra danh sáách rch rỗỗng:ng: isEmptyList(SingleList *list):

Biến đếm last nhận giá trị ngoài khoảng [0, MAXSIZE-1];

�� KiKiểểm tra danh sm tra danh sáách đch đầầy:y: isFullList(SingleList *list):

12.3. Cài đặt danh s ách sử dụng mảng

0 MAXSIZE - 1

last

-1

24/09/201312

�� KhKhởởi ti tạạo danh so danh sáách:ch: makeEmptyList(SingleList *list):

Biến đếm last nhận giá trị ngoài khoảng [0, MAXSIZE-1];

�� KiKiểểm tra danh sm tra danh sáách rch rỗỗng:ng: isEmptyList(SingleList *list):

Biến đếm last nhận giá trị ngoài khoảng [0, MAXSIZE-1];

�� KiKiểểm tra danh sm tra danh sáách đch đầầy:y: isFullList(SingleList *list):

last = MAXSIZE-1;

12.3. Cài đặt danh s ách sử dụng mảng

0 MAXSIZE - 1

last =MAXSIZE - 1

24/09/201313

�� Thêm mThêm mộột pht phầần tn tửử vvàào đo đầầu ds:u ds:

insertToList(*list, 1, v);

1. Kiểm tra mảng đầy hay không;

2. Dịch chuyển danh sách về cuối mảng đi 1 ô nhớ;

3. Gán giá trị thêm vào cho ô nhớ đầu tiên của mảng;

4. Tăng biến đếm last;

12.3. Cài đặt danh s ách sử dụng mảng

MAXSIZE - 1

first = 0 last

v

0

24/09/201314

�� Thêm mThêm mộột pht phầần tn tửử vvàào cuo cuốối ds:i ds:

insertToList(*list, last +1, v);

1. Kiểm tra mảng đầy hay không;

2. Tăng biến đếm last;

3. Gán giá trị mới vào ô nhớ last;

12.3. Cài đặt danh s ách sử dụng mảng

MAXSIZE - 1

last

v

0

24/09/201315

�� Thêm mThêm mộột pht phầần tn tửử vvàào vo vịị trtríí p trên ds:p trên ds:

insertToList(*list,p, v);

1. Kiểm tra mảng đầy hay không;

2. Kiểm tra tính hợp lệ của vị trí cần đưa phần tử mới vào;

3. Dịch chuyển các phần tử trong khoảng [p-1, last] về phía cuối mảng 1 ô nhớ;

4. Tăng biến đếm last;

5. Gán giá trị mới vào ô nhớ last;

12.3. Cài đặt danh s ách sử dụng mảng

MAXSIZE - 1

last

v

p-1

0

24/09/201316

�� XXóóa pha phầần tn tửử ởở đ đầầu danh su danh sáách:ch:

deleteFromList(*list, 1);

1. Kiểm tra mảng rỗng hay không;

2. Lấy giá trị của phần tử đầu tiên;

3. Dịch chuyển phần còn lại của danh sách về đầu mảng;

4. Giảm biến đếm last;

12.3. Cài đặt danh s ách sử dụng mảng

MAXSIZE - 1

last

v

0

24/09/201317

�� XXóóa pha phầần tn tửử ởở cucuốối danh si danh sáách:ch:

deleteFromList(*list, last +1);

1. Kiểm tra mảng rỗng hay không;

2. Lấy giá trị của phần tử cuối của danh sách;

3. Giảm biến đếm last;

12.3. Cài đặt danh s ách sử dụng mảng

MAXSIZE - 1

last

v

0

24/09/201318

�� XXóóa pha phầần tn tửử ởở vvịị trtríí cho trư cho trư ớớc:c:

deleteFromList(*list, p);

1. Kiểm tra mảng rỗng hay không;

2. Kiểm tra tính hợp lệ của vị trí cần xóa;

3. Dịch chuyển các phần tử trong khoảng [p, last] về đầu mảng 1 ô nhớ;

4. Giảm biến đếm last;

12.3. Cài đặt danh s ách sử dụng mảng

MAXSIZE - 1

last

v

0

p-1

24/09/201319

12.3. Cài đặt danh s ách sử dụng mảng

�� ĐĐáánh ginh giáá vvềề phư ơng ph phư ơng phááp cp càài đi đặặt: t: Do sử dụng mảng, các phần tử được lưu trữ là một dãy liên tiếp trong bộ nhớ, nên sử dụng mảng để quản lý ds có một số ưu nhược điểm sau:

�� Ưu điƯu điểểm:m:� Mật độ sử dụng bộ nhớ là tối ưu tuyệt đối;

� Việc truy xuất đến một phần tử là nhanh chóng và dễ dàng thông qua chỉ số mảng;

�� NhưNhư ợợc đic điểểm:m:� Việc thêm bớt các phần tử là khó khăn, tốn chi phí dịch

chuyển mảng;

� Đôi khi lãng phí bộ nhớ vì không sử dụng đến;

24/09/201320

12.3. Cài đặt danh s ách sử dụng mảng

�� GiGiảải phi phááp: p: cài đặt danh sách bằng con trỏ liên kliên kếết đt độộngng:� Để khắc phục nhược điểm trên, có thể sử dụng liên kết

động như là cấu trúc dữ liệu thay thế;

� 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, không cần (không thể) 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;

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

24/09/201321

Lecture 12 – Linked Lists

12.1. Khái niệm về danh sách

12.2. Các phép toán trên danh sách

12.3. Cài đặt danh sách sử dụng mảng

12.4. Danh s12.4. Danh sáách liên kch liên kếết đơnt đơn

12.5. Danh sách liên kết dạng vòng

12.6. Danh sách liên kết kép

12.7. Ứng dụng của danh sách liên kết

12.8. Bài tập thực hành

24/09/201322

12.4. Danh s ách liên k ết đơn

�� Danh sDanh sáách liên kch liên kếết đơn 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.

LinkData

Node

next

60

1000

800 45

800

90 55

90

0 NULL

24/09/201323

�� KhKháái nii niệệm: m: 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 trỏ đến nút tiếp theo.

� Khai báo trong C:

typedef int DataType; // kiểu dữ liệu dùng trong danh sách

typedef struct Node{DataType data;// Dùng đểchứa dữ liệu kiểu DataTypeNode *next; // Con trỏ tới ô nhớ Node kế tiếp

};

12.4. Danh s ách liên k ết đơn

v v v v NULL

Giá trị củanode

Con trỏ đếnphần tử tiếp

theo

24/09/201324

� Để quản lý danh sách liên kết đơn, thông thường cần:

�� firstfirst 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 (lastlast) liên kết với NULL.

� Khai báo pt của ds trong C:

typedef int DataType; // kiểu dữ liệu dùng trong danh sách

typedef struct Node{DataType data;// Dùng đểchứa dữ liệu kiểu DataTypeNode *next; // Con trỏ tới ô nhớ Node kế tiếp

};

12.4. Danh s ách liên k ết đơn

v v v v NULLfirst …

24/09/201325

12.4. Danh s ách liên k ết đơn

�� CCáác thao tc thao táác cơ bc cơ bảản khi ln khi lààm vim việệc vc vớới danh si danh sáách đch độộng:ng:� Khởi tạo danh sách;

� insertAtFirst(*list, v): Thêm một node vào đầu danh sách;

� insertAtPos(*list, v, p): Chèn một node vào danh sách;

� insertAtLast(*list, v): Thêm một node vào cuối danh sách;

� deleteAtFirst(*list): Xóa node từ đầu danh sách;

� deleteAtLast(*list): Xóa node ở cuối danh sách;

� deleteAtPos(*list, pos) : Xóa một node trong danh sách.

� isEmptyList(*list): Kiểm tra danh sách rỗng;

� makEmptyList(*list): Làm rỗng danh sách;

� searchList(*list, v): Tìm một giá trị trong danh sách.

24/09/201326

12.4. Danh s ách liên k ết đơn

�� KhKhởởi ti tạạo danh so danh sáách:ch:

typedef int DataType;

typedef struct Node{

DataType data; // Dùng để chứa dữ liệu kiểu DataType

Node *next; // Con trỏ tới ô nhớ Node kế tiếp

};

typedef Node* List;

int main(){

List L = NULL; // tạo ra một danh sách rỗng với phần tử đầu tiên là first;

....

NULL

first

24/09/201327

�� Thêm mThêm mộột pht phầần tn tửử vvàào đo đầầu u danh sdanh sáách:ch:

1. Tạo ra node mới;

2. Cho con trỏ của node mới tạo ra trỏ đến first;

3. Gán first bằng node mới tạo ra.

void insertAtFirst(List *first, DataTypeinfo){

Node *temp;

temp = (Node*)malloc(sizeof(Node));

temp->data = info;

temp->next=*first;

(*first) = temp;

}

12.4. Danh s ách liên k ết đơn

v v NULL…v

temp

NULL

firstfirst

vtemp

NULL

24/09/201328

�� Thêm pt vThêm pt vàào cuo cuốối danh si danh sáách:ch:

void insertAtLast(List *first, DataType info);1. Nếu ds rỗng thì thêm vào phần tử đầu tiên của danh sách;

2. Nếu danh sách không rỗng, dùng một biến tạm temp1 duyệt lần lượt từ đầu đến phần tử cuối cùng của danh sách;

3. Tạo ra một node mới temp chứa giá trị cần đưa vào;

4. Cho con trỏ của temp1 trỏ đến temp;

5. Cho con trỏ của temp trỏ đến null;

12.4. Danh s ách liên k ết đơn

v v

v

v NULLfirst …

temp1temp

24/09/201329

�� Thêm pt vThêm pt vàào vo vịị trtríí bbấất kt kỳỳ::

void insertAtPos(List *first, DataType info, int pos);1. Nếu ds rỗng thì thêm vào phần tử đầu tiên;

2. Nếu danh sách không rỗng, dùng một biến tạm temp1 duyệt lần lượt từ đầu đến khi đến vị trí cần thêm vào hoặc đến hết danh sách;

3. Nếu vị trí ngoài danh sách thì thoát khỏi thủ tục;

4. Tạo ra một node mới temp chứa giá trị cần đưa vào;

5. Cho con trỏ của temp trỏ đến temp1->next;

6. Cho con trỏ của temp1 trỏ đến temp;

12.4. Danh s ách liên k ết đơn

v v

v

NULLfirst v

temp

v v

temp1

24/09/201330

�� XXóóa ma mộột pht phầần tn tửử ởở đ đầầu danh su danh sáách:ch:

void deleteAtFirst(List *first);

1. Nếu ds rỗng thì thoát khỏi thủ tục;

2. Nếu danh sách không rỗng, dùng một biến tạm temp gán bằng first;

3. Cho first bằng phần tử tiếp theo trong danh sách;

4. Gọi lệnh giải phóng bộ nhớ cho biến temp;

12.4. Danh s ách liên k ết đơn

v v v v NULL…

temp

first

24/09/201331

�� XXóóa ma mộột pht phầần tn tửử ởở cucuốối danh si danh sáách:ch:

void deleteAtLast(List *first);1. Nếu ds rỗng thì thoát khỏi thủ tục;2. Dùng hai biến tạm temp1 và temp2, lúc đầu cả hai trỏ đến first;3. Lần lượt duyệt danh sách sao cho temp1 là phần tử liền trước của

temp2 đến khi temp2 là phần tử cuối cùng của danh sách (temp2->next ==NULL);

4. Cho con trỏ của temp1 trỏ đến NULL;5. Giải phóng bộ nhớ cho temp2;

12.4. Danh s ách liên k ết đơn

v v NULLv

temp2

v v

temp1

24/09/201332

�� XXóóa ma mộột pht phầần tn tửử ởở vvịị trtríí bbấất kt kỳỳ::

void deleteAtPos(List *first, int pos);1. Nếu ds rỗng thì thoát khỏi thủ tục;

2. Dùng hai biến tạm temp1 và temp2, lúc đầu cả hai trỏ đến first;

3. Lần lượt duyệt danh sách sao cho temp1 là phần tử liền trước của temp2 đến khi temp2 là phần tử cần tìm (bằng cách đếm vị trí của nó);

4. Nếu không tìm thấy thì thoát khỏi thủ tục;

5. Cho con trỏ của temp1 trỏ đến temp2->next;

6. Giải phóng bộ nhớ cho temp2;

12.4. Danh s ách liên k ết đơn

v v NULLv

temp2

temp1

vv v

p

24/09/201333

�� LLààm rm rỗỗng danh sng danh sáách:ch:

1. Nếu ds rỗng thì thoát khỏi thủ tục;

2. Lặp lại lệnh xóa phần tử ở đầu danh sách cho đến khi danh sách rỗng

void makeEmptyList(List *list)

{

while(!isEmptyList(list))deleteAtFirst(list);

}

12.4. Danh s ách liên k ết đơn

v v v v NULL…

temp

first

temp

24/09/201334

Lecture 12 – Linked Lists

12.1. Khái niệm về danh sách

12.2. Các phép toán trên danh sách

12.3. Cài đặt danh sách sử dụng mảng

12.4. Danh sách liên kết đơn

12.5. Danh s12.5. Danh sáách liên kch liên kếết dt dạạng vòngng vòng

12.6. Danh sách liên kết kép

12.7. Ứng dụng của danh sách liên kết

12.8. Bài tập thực hành

24/09/201335

�� KhKháái nii niệệm: m: Danh sách liên kết đơn dạng vòng là danh sách liên kết đơn mà con trỏcủa phần tử cuối cùng sẽ trỏ đến phần tử đầu tiên.

� Khai báo kiểu phần tử:

typedef int DataType; // kiểu dữ

liệu dùng trong danh sách

typedef struct Node{

DataType data;// Dùng để chứa dữ liệu kiểu DataType

Node *next; // Con trỏ tới ô nhớ Node kế tiếp

};

12.5. Circular linked List

v v vfirst …

last

24/09/201336

�� Thêm phThêm phầần tn tửử vvàào đo đầầu ds:u ds:

� Trư ờng hợp 1 – ds rỗng:

1. Tạo ra node mới;

2. Gán first bằng node mới tạo ra;

3. Cho con trỏ của node mới tạo ra trỏ đến first (trỏ đến chính nó);

� Trường hợp 2 – ds không rỗng:

1. Tìm ra phần tử cuối cùng của danh sách (last);

2. Tạo ra node mới;

3. Cho con trỏ của node mới tạo ra trỏ đến first;

4. Gán first = node mới tạo ra;

5. Cho con trỏ của last trỏ tới first.

12.5. Circular linked List

v v vfirst …

last

v

NULL

firstv

24/09/201337

�� Thêm mThêm mộột pht phầần tn tửử vvàào vo vịị trtríí bbấất kt kỳỳ::void insertAtPos(List *first, DataType info, int pos);

1. Nếu ds rỗng thì thêm vào phần tử đầu tiên;2. Nếu danh sách không rỗng, dùng một biến tạm temp1 duyệt lần lượt

từ đầu đến khi đến vị trí cần thêm vào hoặc đến hết danh sách (bằng cách đếm vị trí);

3. Nếu vị trí ngoài danh sách thì thoát khỏi thủ tục;4. Tạo ra một node mới temp chứa giá trị cần đưa vào;5. Cho con trỏ của temp trỏ đến temp1->next;6. Cho con trỏ của temp1 trỏ đến temp;

12.5. Circular linked List

v v

v

first v

temp

v v

temp1

24/09/201338

�� Thêm mThêm mộột pht phầần tn tửử vvàào đuôi o đuôi circularListcircularList::

� Trư ờng hợp 1 – ds rỗng:

1. Tạo ra node mới temp;

2. Gán first bằng temp;

3. Cho con trỏ của temp trỏ đến first (trỏ đến chính nó);

� Trư ờng hợp 2– ds không rỗng:

1. Tìm ra phần tử cuối last của danh sách;

2. Tạo ra node mới temp;

3. Cho con trỏ của temp trỏ đến first ;

4. Cho con trỏ của last trỏ tới temp.

12.5. Circular linked List

v v vfirst …

last

v

temp

24/09/201339

�� XXóóa ma mộột pht phầần tn tửử ởở đ đầầu circularListu circularList::

1. Kiểm tra danh sách rỗng;

2. Tìm ra phần tử cuối last của danh sách;

3. Tạo ra node tạm thời temp và gán nó bằng first;

4. Gán first bằng node tiếp theo trong danh sách;

5. Cho con trỏ của last tạo ra trỏ đến first;

6. Giải phóng bộ nhớ của temp.

12.5. Circular linked List

v v v…

first last

v

temp

24/09/201340

� Xóa một phần tử ở đuôi circularList:

1. Kiểm tra danh sách rỗng;

2. Tìm ra phần tử cuối temp2 của danh sách và phần tử temp1 liền trước nó;

3. Cho con trỏ của temp1 trỏ đến first;

4. Giải phóng bộ nhớ của temp2.

12.5. Circular linked List

v v v…

temp1

vfirst

temp2

24/09/201341

�� XXóóaa mmộộtt phphầầnn ttửử ởở vvịị trtríí bbấấtt kkỳỳ: : void deleteAtPos(List *first, int pos);

1. Nếu ds rỗng thì thoát khỏi thủ tục;

2. Dùng hai biến tạm temp1 và temp2 , lúc đầu cả hai trỏ đến first;

3. Lần lượt duyệt danh sách sao cho temp1 là phần tử liền trước của temp2 đến khi temp2 là phần tử cần tìm (bằng cách đếm vị trí của nó);

4. Nếu không tìm thấy thì thoát khỏi thủ tục;

5. Cho con trỏ của temp1 trỏ đến temp2 ->next;

6. Giải phóng bộ nhớ cho temp2;

12.5. Circular linked List

v vv

temp2temp1

vv v

p

24/09/201342

Lecture 12 – Linked Lists

12.1. Khái niệm về danh sách

12.2. Các phép toán trên danh sách

12.3. Cài đặt danh sách sử dụng mảng

12.4. Danh sách liên kết đơn

12.5. Danh sách liên kết dạng vòng

12.6. Danh s12.6. Danh sáách liên kch liên kếết kt kéépp

12.7. Ứng dụng của danh sách liên kết

12.8. Bài tập thực hành

24/09/201343

12.6. Double linked List

�� KhKháái nii niệệm vm vềề danh sdanh sáách liên kch liên kếết kt kéépp:

� Với các danh sách liên kết đơn, một số vấn đề xuất hiện:

� 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 nào đó trong chuỗi bị hỏng, các phần tử sau đó không dùng được.

� Để giải quyết vấn đề trên, có thể thêm cho mỗi phần tửmột liên kết nữa, liên kết này có chiều ngư ợc lại. Khi thêm mỗi node một liên kết như vậy, danh sách liên kết được gọi là có liên kliên kếết kt kéépp.

24/09/201344

�� KhKháái nii niệệm: m: Danh sách liên kết kép là danh sách liên kết sử dụng 2 con trỏ cho mỗi phần tử, một con trỏ để trỏ đến phần tử tiếp theo trong danh sách, một con trỏ đểtrỏ đến phần tử liền trước nótrong danh sách.

typedef int DataType; // kiểu dữliệu dùng trong danh sáchtypedef struct Node{

DataType data;// Dùng để chứa dữ liệu kiểu DataTypeNode *previos; // Con trỏ trỏ đến ô nhớ liền trước nó;Node *next; // Con trỏ tới ô nhớ Node kế tiếp

};

12.6. Double linked List

first last

v … NULLv vNULL

24/09/201345

� Để quản lý danh sách liên kết kép, thông thư ờng cần:

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

�� lastlast 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 next trỏ tới NULL;

� Bằng cách sử dụng hợp lý liên kết previos hay next, có thể duyệt danh sách theo 2 chiều, về trước hay về sau.

�� Lư u ý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.

12.6. Double linked List

first last

v … NULLv vNULL

datadata - Dữliệu của node

v

nextnext - Con trỏ đếnnode liền sau

previousprevious - Con trỏđến node liền trước

Node

24/09/201346

�� Khai bKhai bááo kio kiểểu phu phầần tn tửử ccủủa ds liên ka ds liên kếết kt kéép trong C:p trong C:

typedef int DataType; // kiểu dữ liệu dùng trong danh sách

typedef struct Node

{

DataType data; // Dùng để chứa dữ liệu kiểu DataType;

Node *previous; // Con trỏ tới ô nhớ Node liền trước

Node *next; // Con trỏ tới ô nhớ Node kế tiếp

};

12.6. Double linked List

first last

v … NULLv vNULL

24/09/201347

�� CCáác thao tc thao táác cơ bc cơ bảản cn củủa danh sa danh sáách liên kch liên kếết kt kéép:p:

� Khởi tạo danh sách;

� insertAtFirst(*list, v): Thêm một node vào đầu danh sách;

� insertAtPos(*list, v, p): Chèn một node vào danh sách;

� insertAtLast(*list, v): Thêm một node vào cuối danh sách;

� deleteAtFirst(*list): Xóa node từ đầu danh sách;

� deleteAtLast(*list): Xóa node ở cuối danh sách;

� deleteAtPos(*list, pos) : Xóa một node trong danh sách.

12.6. Double linked List

first last

v … NULLv vNULL

24/09/201348

� isEmptyList(*list): Kiểm tra danh sách rỗng;

� makEmptyList(*list): Làm rỗng danh sách;

� searchList(*list, v): Tìm một giá trị trong danh sách.

�� KhKhởởi ti tạạo danh so danh sáách:ch:

� Có thể dùng 2 biến để quản lý 2 đầu vào của danh sách bằng cách tạo ra 2 con trỏ first và last, ban đầu, gán cho chúng bằng rỗng;

int main(){

Node* first = NULL;

Node* last = NULL;

12.6. Double linked List

first last

NULL

24/09/201349

�� Thêm mThêm mộột pht phầần tn tửử vvàào đo đầầu u danh sdanh sááchch::

� Trư ờng hợp 1 – ds rỗng:

1. Tạo ra một node mới tempchứa dữ liệu cần đưa vào;

2. Cho con trỏ previous và nextcủa temp trỏ đến NULL;

3. Cho first, last trỏ đến temp.

� Trư ờng hợp 2 – ds không rỗng:

1. Tạo ra một node mới temp chứa dữ liệu cần đưa vào;

2. Cho con trỏ previous của temptrỏ đến NULL;

3. Cho con trỏ next của temp trỏ đến first;

4. Cho con trỏ previous của first trỏ đến temp;

5. Cho first trỏ đến temp.

12.6. Double linked List

first last

v NULLNULL

first last

v … NULLv vNULL NULL

temp

24/09/201350

�� Thêm mThêm mộột pht phầần tn tửử vvàào cuo cuốối i danh sdanh sáách:ch:

� Trư ờng hợp 1 – ds rỗng:

1. Tạo ra một node mới tempchứa dữ liệu cần đưa vào;

2. Cho con trỏ previous và nextcủa temp trỏ đến NULL;

3. Cho first, last trỏ đến temp.

� Trư ờng hợp 2 – ds không rỗng:

1. Tạo ra một node mới temp chứa dữ liệu cần đưa vào;

2. Cho con trỏ next của last trỏ đến temp;

3. Cho con trỏ next của temp trỏ đến NULL;

4. Cho con trỏ previous của temptrỏ đến last;

5. Cho last trỏ đến temp.

12.6. Double linked List

v

first last

v … v NULLNULL NULL

temp

24/09/201351

�� Thêm phThêm phầần tn tửử vvàào sau mo sau mộột vt vịị trtríí cho trư cho trư ớớc:c:

1. Tìm kiếm phần tử curr liền trước vị trí cần thêm vào;

2. Tạo ra một node mới temp chứa dữ liệu nhập vào;

3. Cho con trỏ previous của phần tử liền sau curr trỏ đến temp;

4. Cho con trỏ next của temp trỏ đến phần tử liền sau curr;

5. Cho con trỏ previous của temp trỏ đến curr;

6. Cho con trỏ next của curr trỏ đến temp.

12.6. Double linked List

v

v

… v …

curr

24/09/201352

�� XXóóa pha phầần tn tửử ttừừ đ đầầu danh su danh sáách:ch:

� Trường hợp 1 – ds có 1 phần tử:

1. Tạo ra con trỏ temp trỏ đến first;

2. Gán first và last bằng NULL;

3. Gọi lệnh giải phóng bộ nhớ cho temp.

� Trường hợp tổng quát:

1. Tạo ra con trỏ temp trỏ đến first;

2. Gán first bằng first->next;

3. Gán first->previous bằng NULL;

4. Gọi lệnh giải phóng bộ nhớcho temp.

12.6. Double linked List

first

v …v NULLNULL

temp

v

24/09/201353

�� XXóóa pha phầần tn tửử ởở cucuốối danh si danh sáách. ch. Trường hợp tổng quát:

1. Tạo ra con trỏ temp trỏ đến last;

2. Gán last bằng last->previous;

3. Gán last->next bằng NULL;

4. Gọi lệnh giải phóng bộ nhớ cho temp.

12.6. Double linked List

last

v… v NULLNULL

temp

v

24/09/201354

�� XXóóa pha phầần tn tửử ởở vvịị trtríí sau sau (t(trưrư ớớc) vc) vịị trtríí cho trư cho trư ớớc:c:

1. Tìm ra phần tử liền trước curr (hoặc liền sau) của phần tử cần xóa;

2. Tạo ra con trỏ temp trỏ đến phần tử cần xóa;

3. Gán ((curr->next)->next)->previous bằng curr;

4. Gán curr->next bằng ((curr->next)->next);

5. Gọi lệnh giải phóng bộ nhớ cho temp.

12.6. Double linked List

v

temp

… v v …

curr

24/09/201355

� Trong thực tế, có thể tổ chức thành danh sách liên kết kép vòng, liên kết next của phần tử cuối last trỏ vào phần tử đầu tiên (do first quản lý), liên kết previous của phần tử đầu tiên (first) trỏ tới phần tử cuối cùng.

12.6. Double linked List

first

last

v …v v

24/09/201356

12.6. Double linked List

�� ĐĐáánhnh gigiáá vvềề ccààii đđặặtt danhdanh ssááchch bbằằngng con con trtrỏỏ đđộộngng: : Do các phần tử của ds có thể không nằm liên tiếp nhau trong bộ nhớ, dẫn đến:

�� NhưNhư ợợc đic điểểm:m:� Sử dụng bộ nhớ không tối ưu;� Việc truy xuất đến một phần tử tính mất nhiều thời gian, thời

gian tìm kiếm là O(n), với n là số phần tử của danh sách do phải duyệt qua các phần tử khác;

�� Ưu điƯu điểểm:m:� Tận dụng được các không gian rỗng của bộ nhớ mà ko chứa được

mảng lớn, nếu dữ liệu trên mỗi phần tử là lớn thì cách này tỏ ra hiệu quả, ngược lại, lãng phí bộ nhớ dành cho con trỏ;

� Việc thêm bớt các phần tử là dễ dàng, và chỉ việc thay đổi mối liên kết giữa con trỏ;

24/09/201357

Lecture 12 – Linked Lists

12.1. Khái niệm về danh sách

12.2. Các phép toán trên danh sách

12.3. Cài đặt danh sách sử dụng mảng

12.4. Danh sách liên kết đơn

12.5. Danh sách liên kết dạng vòng

12.6. Danh sách liên kết kép

12.7. 12.7. ỨỨng dng dụụng cng củủa danh sa danh sáách liên kch liên kếếtt

12.8. Bài tập thực hành

24/09/201358

12.7. Ứng dụng của Linked lists

� Trong thực tế, danh sách liên kết được sử dụng rộng rãi trong các chương trình máy tính, ví dụ:

� Sử dụng danh sách liên kết xây dựng Stack và Queue;

� Biểu diễn cây, đồ thị bằng danh sách liên kết;

� Biểu diễn ma trận thưa bằng danh sách liên kết;

� Bài toán đa thức sử dụng danh sách liên kết;

� Bài toán số lớn sử dụng danh sách liên kết;

� Xây dựng bảng băm;

� …

24/09/201359

Lecture 12 – Linked Lists

12.1. Khái niệm về danh sách

12.2. Các phép toán trên danh sách

12.3. Cài đặt danh sách sử dụng mảng

12.4. Danh sách liên kết đơn

12.5. Danh sách liên kết dạng vòng

12.6. Danh sách liên kết kép

12.7. Ứng dụng của danh sách liên kết

12.8. B12.8. Bàài ti tậập thp thựực hc hàànhnh

24/09/201360

12.8. Bài t ập thực hành

1.Viết chương trình con thêm một phần tử trong danh sách liên kết đã có thứ tự sao cho ta vẫn có một danh sách có thứ tự.

2.Viết chương trình con tìm kiếm và xóa một phần tử trong danh sách liên kết có thứ tự.

3.Viết chương trình con loại bỏ các phần tử trùng nhau (giữ lại duy nhất 1 phần tử) trong một danh sách liên kết có thứ tựkhông giảm

4.Viết chương trình con đảo ngược một danh sách liên kết.

5.Viết chương trình con xóa khỏi danh sách liên kết lưu trữ các số nguyên các phần tử là số nguyên lẻ

6.Viết chương trình con tách một danh sách liên kết chứa các sốnguyên thành hai danh sách: một danh sách gồm các số chẳn còn cái kia chứa các số lẻ.

24/09/201361

12.8. Bài t ập thực hành

8.Ðể lưu trữ một số nguyên lớn, ta có thể dùng danh sách liên kết chứa các chữ số của nó. Hãy tìm cách lưu trữ các chữ sốcủa một số nguyên lớn theo ý tưởng trên sao cho việc cộng hai số nguyên lớn là dễ dàng thực hiện. Viết chương trình con cộng hai số nguyên lớn

9.Ða thức P(x)= anxn+ an-1xn-1+... + a1x + a0 được lưu trữ trong máy tính dưới dạng một danh sách liên kết mà mỗi phần tửcủa danh sách là một bản ghi có ba trường lưu giữ hệ số, sốmũ, và trưòng con trỏ để trỏ đến phần tử kế tiếp. Chú ý cách lưu trữ đảm bảo thứ tự giảm dần theo số mũ của từng hạng tửcủa đa thức:

� Hãy viết khai báo thực hiện được sự lưu trữ này.� Dựa vào sự cài đặt ở trên, viết chương trình con thực hiện việc cộng

hai đa thức.� Viết chương trình con tính giá trị và lấy đạo hàm của đa thức.

24/09/201362

12.8. Bài t ập thực hành

9.Ða thức P(x)= anxn+ an-1xn-1+... + a1x + a0 được lưu trữtrong máy tính dưới dạng một mảng theo nguyên theo các cách sau:

� Cách 1: Phần tử đầu tiên trong mảng lưu trữ bậc n của đa thức. n + 1 phần tử tiếp theo lần lượt lưu các hệ số từ an đến a0;

� Cách 2: Phần tử đầu tiên trong mảng lưu trữ k là số các hệsố khác 0. 2k phần tử tiếp theo lưu trữ k cặp {hệ số, mũ} tương ứng

� Viết chương trình con thực hiện việc cộng hai đa thức.

� Viết chương trình con tính giá trị và lấy đạo hàm của đa thức.

24/09/201363

Recommended