Môn: CẤU TRÚC DỮ LIỆU

120
1 Môn: CẤU TRÚC DỮ LIỆU Chương 4: DANH SÁCH (LIST)

description

Môn: CẤU TRÚC DỮ LIỆU. Chương 4: DANH SÁCH (LIST). NỘI DUNG CHƯƠNG 4. Khái niệm danh sách Các phép toán trên danh sách Danh sách đặc Định nghĩa Biểu diễn danh sách đặc Các thao tác trên danh sách đặc Ưu nhược điểm và ứng dụng Danh sách liên kết Định nghĩa Danh sách liên kết đơn - PowerPoint PPT Presentation

Transcript of Môn: CẤU TRÚC DỮ LIỆU

Page 1: Môn: CẤU TRÚC DỮ LIỆU

1

Môn: CẤU TRÚC DỮ LIỆU

Chương 4: DANH SÁCH (LIST)

Page 2: Môn: CẤU TRÚC DỮ LIỆU

2

NỘI DUNG CHƯƠNG 41. Khái niệm danh sách2. Các phép toán trên danh sách3. Danh sách đặc

Định nghĩa Biểu diễn danh sách đặc Các thao tác trên danh sách đặc Ưu nhược điểm và ứng dụng

4. Danh sách liên kết Định nghĩa Danh sách liên kết đơn Danh sách liên kết kép Ưu nhược điểm của danh sách liên kết

5. Danh sách hạn chế Hàng đợi Ngăn xếp Ứng dụng của danh sách hạn chế

BÀI TẬP

Page 3: Môn: CẤU TRÚC DỮ LIỆU

3

1. Khái niệm danh sách Danh sách a1, a2, ….aN là tập hợp các phần tử có

kiểu dữ liệu xác định và giữa chúng có 1 mối quan hệ nào đó. Nếu biết phần tử ai vị trí của phần tử ai+1

Số phần tử trong một danh sách là chiều dài của 1 danh sách. Danh sách rỗng là danh sách có chiều dài = 0

Page 4: Môn: CẤU TRÚC DỮ LIỆU

4

2. Các phép toán trên danh sáchTùy theo loại của từng danh sách sẽ có các phép toán khác nhau,

các phép toán thông thường như sau:2.1. Tạo mới 1 danh sách Đưa vào danh sách nội dung các phần tử. Chiều dài của danh sách là xác định.2.2. Thêm 1 phần tử vào danh sách Khi thêm 1 phần tử chiều dài danh sách tăng lên. Có thao tác thêm vào đầu, cuối hay tại 1 vị trí xác định của

danh sách.2.3. Tìm kiếm 1 phần tử trong danh sách Tìm 1 phần tử trong danh sách thỏa mãn điều kiện nào đó Dùng các thuật toán tìm kiếm trong chương “Tìm kiếm”2.4. Loại bớt 1 phần tử trong danh sách Chiều dài danh sách giảm xuống 1 phần tử Công việc loại bớt cũng bao gồm thao tác tìm kiếm ra phần tử

cần hủy trong danh sách.

Page 5: Môn: CẤU TRÚC DỮ LIỆU

5

2. Các phép toán trên danh sách (tt)2.5. Sửa đổi giá trị 1 phần tử trong danh sách Thay đổi thông tin của 1 phần tử trong danh sách Công việc cập nhật phần tử cũng bao gồm thao tác tìm kiếm

ra phần tử cần hủy trong danh sách.2.6. Sắp xếp danh sách Dùng các thuật toán trong chương sắp xếp.2.7. Tách danh sách thành nhiều danh sách con Tách danh sách thành các DS con theo 1 quy luật chia nào đó Tổng chiều dài các danh sách được chia bằng chiều dài danh

sách ban đầu2.8. Nhập nhiều danh sách thành 1 danh sách Nhập các danh sách thành 1 danh sách Tổng chiều dài danh sách bằng tổng chiều dài các danh sách

ban đầu Có thể ghép đuôi các danh sách hay trộn lẫn theo 1 phương

pháp nhất định2.9. Sao chép 1 danh sách: Sao chép toàn bộ nội dung của danh

sách thành 1 danh sách khác.2.10. Hủy danh sách: Huỷ nội dung hay cả vùng nhớ chứa DS

Page 6: Môn: CẤU TRÚC DỮ LIỆU

6

3. Danh sách đặc (Condensed List)3.1. Định nghĩa Danh sách đặc là danh sách mà không gian bộ nhớ lưu trữ

các phần tử nằm kề cận nhau trong bộ nhớ.3.2. Biểu diễn danh sách đặc Biểu diễn danh sách đặc dùng 1mảng các phần tử có kiểu dử

liệu là kiểu dữ liệu của các phần tử trong danh sách Cần biết chiều dài tối đa của một danh sách đặc thông qua 1

biến. Cần biết chiều dài thực của một danh sách đặc thông qua 1

biến.VD:#define MaxLength 1000

int RealLength;T CD_List[MaxLength]

Hay: T * CD_List = new T[MaxLength]

Page 7: Môn: CẤU TRÚC DỮ LIỆU

7

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặcMột số thao tác trên danh sách đặc được thống kê tóm tắt:

3.3.1. Khởi tạo danh sáchKhởi tạo danh sách cho chiều dài danh sách trở về 0.void Khoitao(int &Len){

Len = 0;return;

}

Page 8: Môn: CẤU TRÚC DỮ LIỆU

8

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặc (tt)3.3.2. Tạo danh sách mới & nhập danh sáchTạo danh sách mới có chiều dài tối đa MaxLen, hàm trả về giá trị

thực của danh sách mới được tạo.int TaoDanhSach(int M[], int &Len){

if (Len > MaxLen)Len = MaxLen;

for (int I = 0; i< Len;I++)M[I] = Nhapphantu();

return (Len);}Int Nhapphantu(){ …}

Page 9: Môn: CẤU TRÚC DỮ LIỆU

9

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặc (tt)3.3.3. Thêm 1 phần tử vào danh sáchThêm 1 phần tử có giá trị NewValue vào trong danh sách có chiều dài

Length tại vị trí InsPosB1: IF (Length = MaxLen)

Thực hiện BKTB2: Pos = Length+1B3: IF(Pos = InsPos)

Thực hiện B7B4: M[Pos] = M[Pos -1]B5: Pos--B6: Lặp lại B3B7:M[InsPos] = NewValueB8: Length++BKT: Kết thúc

Page 10: Môn: CẤU TRÚC DỮ LIỆU

10

3. Danh sách đặc (tt)

3.3. Các thao tác trên danh sách đặc (tt)

3.3.3. Thêm 1 phần tử vào danh sách (tt)

int Themphantu(int M[], int &Len, int x, int InsPos)

{

if (Len == MaxLen)

return (-1);

for (int I = Len; I >InsPos; I++)

M[I] = M[I-1];

M[InsPos] = x;

Len++;

return (Len);

}

Page 11: Môn: CẤU TRÚC DỮ LIỆU

11

3. Danh sách đặc (tt)

3.3. Các thao tác trên danh sách đặc (tt)

3.3.4. Tìm kiếm 1 phần tử trong danh sách

Dùng các thuật toán tìm kiếm tìm phần tử thỏa mãn điều kiện trong danh sách

Tìm kiếm tuyến tính Tìm nhị phân

Page 12: Môn: CẤU TRÚC DỮ LIỆU

12

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặc (tt)3.3.5. Hủy 1 phần tử trong danh sách Loại bỏ phần tử có vị trí DelPos trong danh sách M có chiều dài

Length (có thể có thao tác tìm kiếm xác định vị trí xóa phần tử)Thuật toán:B1: IF(Length =0 OR DelPos > Len) Thực hiện BKTB2: Pos = DelPosB3: IF(Pos = Length)

Thực hiện B7B4: M[Pos] = M[Pos+1]B5: Pos++B6: Lặp lại B3B7: Length--BKT: Kết thúc

Page 13: Môn: CẤU TRÚC DỮ LIỆU

13

3. Danh sách đặc (tt)

3.3. Các thao tác trên danh sách đặc (tt)

3.3.5. Hủy 1 phần tử trong danh sách (tt)int Xoaphantu(int M[], int &Len, int DelPos){

int (Len ==0 || DelPos >=Len)return (-1);

for (int I =DelPos; i<Len; i++)M[i] = M[i+1];

Len --;return (Len);

}

Page 14: Môn: CẤU TRÚC DỮ LIỆU

14

3. Danh sách đặc (tt)

3.3. Các thao tác trên danh sách đặc (tt)

3.3.6. Sửa đổi giá trị cho 1 phần tử trong danh sách Giả sử phần tử trong danh sách được thay đổi ở tại vị trí

Position trong danh sách M có chiều dài Length. Thao tác sửa đổi là thao tác tìm kiếm phần tử cần có vị trí

(hay giá trị) và gán giá trị mới M[Pos] = NewValue;

Page 15: Môn: CẤU TRÚC DỮ LIỆU

15

3. Danh sách đặc (tt)

3.3. Các thao tác trên danh sách đặc (tt)

3.3.7. Sắp xếp thứ tự phần tử trong danh sách

Dùng các thuật toán sắp xếp nội Giải thuật sắp xếp nổi bọt (Bubble Sort) Giải thuật sắp xếp dựa trên phân hoạch (Quick Sort) Giải thuật sắp xếp chọn trực tiếp (Straight Selection Sort) Giải thuật sắp xếp chèn trực tiếp (Straight Insertion Sort) Giải thuật sắp xếp trộn trực tiếp (Straight Merge Sort) Giải thuật sắp xếp trộn tự nhiên (Natural Merge Sort)

Page 16: Môn: CẤU TRÚC DỮ LIỆU

16

3. Danh sách đặc (tt)

3.3. Các thao tác trên danh sách đặc (tt)

3.3.8. Tách 1 danh sách thành nhiều danh sách

Có nhiều thao tác tách 1 danh sách thành nhiều danh sách: Phân phối luân phiên theo đường chạy (distribute) Phân phối từng phần của danh sách thành các danh sách con Tách các phần tử thỏa mãn điều kiện cho trước thành các

danh sách con.

Giả sử cần tách danh sách M có chiều dài Length thành các danh sách con SM1, SM2 có chiều dài tương ứng là Slen1 và SLen2

Page 17: Môn: CẤU TRÚC DỮ LIỆU

17

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặc (tt)3.3.8. Tách 1 danh sách thành nhiều danh sách (tt)B1: IF(SLen1 >= Len)

SLen1 = LenSLen2 = 0

B2:IF(SLen2 >= Len)SLen2 = LenSLen1 = 0

B3: IF(SLen1 + SLen2 <> Len) SLen2 = Len – SLen1B4: IF (SLen1 < 0) SLen1 = 0B5: IF (SLen2 < 0) SLen2 = 0B6: I =1, SI = 1B7: IF (I > SLen1) Thực hiện B11B8: SM[SI] = M[I]B9: I++, SI++B10: Lặp lại B7B11: SI = 1B12: IF(I > Len) Thực hiện BKTB13: SM2[SI] = M[I]B14: I++, SI++B15: Lặp lại B12BKT: Kết thúc

Page 18: Môn: CẤU TRÚC DỮ LIỆU

18

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặc (tt)3.3.8. Tách 1 danh sách thành nhiều danh sách (tt)void CS_Split(T M[], int Len, T SM1[], int &SLen1, T SM2[], int &SLen2){ if (Slen1 >=Len) { SLen1 = Len;

Slen2 = 0; }

if (Slen2 >=Len) { SLen2 = Len;

SLen1 = 0; } if (SLen1 < 0) SLen1 = 0; if (SLen2 < 0) SLen2 = 0; if (SLen1 + SLen2 != Len) SLen2 = Len - SLen1;

for (int i=0; i<SLen1; i++) SM1[i] = M[i];for (int j=0; j<SLen2; i++, j++) SM2[j] = M[i];

return;}

Page 19: Môn: CẤU TRÚC DỮ LIỆU

19

3. Danh sách đặc (tt)

3.3. Các thao tác trên danh sách đặc (tt)

3.3.9. Nhập nhiều danh sách thành 1 danh sách

Các cách nhập danh sách: Ghép nối đuôi các danh sách thành danh sách mới có chiều

dài là tổng chiều dài các danh sách. Trộn xen kẽ các phần tử trong danh sách con theo 1 quy luật

nào đó thành 1 danh sách mới (dùng thuật toán merge trong merge sort)

Giả sử cần ghép danh sách SM1, SM2 có chiều dài SLen1, SLen2 thành danh sách M có chiều dài Len = SLen1+SLen2 theo thứ tự từ SM1 đến hết SM2

Page 20: Môn: CẤU TRÚC DỮ LIỆU

20

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặc (tt)3.3.9. Nhập nhiều danh sách thành 1 danh sách(tt)Thuật toán:B1: IF (Slen1+SLen2 > MaxLen) // M không đủ khả năng chứa

Thực hiện BKTB2: I = 1 // Chép từ SM1[] vào M[]B3: IF (I > SLen1)

Thực hiện B7B4: M[I] = SM[I]B5: I++B6: Lặp lại B3B7: SI = 1 // Chép từ SM2[] vào M[]B8: IF (SI > SLen2)

Thực hiện BKTB9: M[I] = SM[SI]B10: I++; SI++B11: Lặp lại B8BKT: Kết thúc

Page 21: Môn: CẤU TRÚC DỮ LIỆU

21

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặc (tt)3.3.9. Nhập nhiều danh sách thành 1 danh sách(tt)int CD_Concat(T SM1[], int SLen1, T SM2[], int SLen2, T M [], int

&Len){

if (SLen1+SLen2 > MaxLen)return (-1);

for (int I = 0; I < SLen1; I++)M[I] = SM1[I];

for (int J = 0; J < SLen2; I++, J++)M[I] = SM1[J];

Len = SLen1+ SLen2;return (Len);

}

Page 22: Môn: CẤU TRÚC DỮ LIỆU

22

3. Danh sách đặc (tt)3.3. Các thao tác trên danh sách đặc (tt)3.3.10. Sao chép 1 danh sách: Sao chép nội dung danh sách thành 1

danh sách khác có cùng chiều dàiThuật toánB1: I = 1B2: IF (I > Length) // Length là chiều dài của dãyB3: CM[I] = M[I]B4: I++B5: Lặp lại B2BKT: Kết thúcint CD_Copy(T M[], int Len, T CM[]) // Hàm trả về chiều dài của DS{ for (int i=0; i< Len; i++)

CM[i] = M[i];return (Len)

}

Page 23: Môn: CẤU TRÚC DỮ LIỆU

23

3. Danh sách đặc (tt)

3.3. Các thao tác trên danh sách đặc (tt)

3.3.11. Hủy danh sách Nếu danh sách được cấp phát động dùng toán tử delete để

hủy. Nếu danh sách được cấp phát tĩnh, việc hủy bỏ chỉ có tác

dụng đưa chiều dài danh sách về 0, việc thu hồi bộ nhớ sẽ do ngôn ngữ lập trình thực hiện

Page 24: Môn: CẤU TRÚC DỮ LIỆU

24

3. Danh sách đặc (tt)

3.4. Ưu nhược điểm và ứng dụng Do phần tử được lưu trữ kề cập với nhau trong bộ nhớ, danh

sách đặc có các ưu điểm: Mật độ sử dụng danh sách là tối ưu tuyệt đối. Truy cập, tìm kiếm các phần tử là dễ dàng vì vị trí các phần

tử liền kề với nhau trong bộ nhớ. Nhược điểm của danh sách là khi thêm hay hủy 1 phần tử

trong danh sách cần dịch chuyển các phần tử còn lại qua vị trí khác.

Được ứng dụng nhiều trong cấu trúc dữ liệu mảng (mảng 1 chiều, mảng nhiều chiều, mảng cấp phát tĩnh, mảng cấp phát động).

Page 25: Môn: CẤU TRÚC DỮ LIỆU

25

4. Danh sách liên kết (Linked List)

4.1. Định nghĩa

4.2. Danh sách liên kết đơn (Simply Linked List)

4.3. Danh sách liên kết kép (Doubly Linked List)

4.4. Ưu nhược điểm của danh sách liên kết

Page 26: Môn: CẤU TRÚC DỮ LIỆU

26

4. Danh sách liên kết (tt)

4.1. Định nghĩa Danh sách liên kết là tập hợp các phần tử mà giữa chúng có

một sự nối kết với nhau thông qua vùng liên kết của chúng. Tùy cách kết nối ràng buộc giữa những phần tử này và phần

tử khác, danh sách liên kết chia thành các loại khác nhau: Danh sách liên kết đơn Danh sách liên kết đôi/kép Danh sách đa liên kết Danh sách liên kết vòng (vòng đơn, vòng đôi)

Mỗi loại danh sách có cách biểu diễn theo các cấu trúc dữ liệu và thao tác trên dữ liệu khác nhau.

Page 27: Môn: CẤU TRÚC DỮ LIỆU

27

4.2. Danh sách liên kết đơn (SLL)4.2.1. Cấu trúc dữ liệu Nội dung mỗi phần tử (nút) trong danh sách liên kết gồm 2

vùng Vùng dữ liệu và Vùng liên kếtstruct Node{ int info;

Node *pNext; // liên kết đến vùng của phần tử kế tiếp

};

Page 28: Môn: CẤU TRÚC DỮ LIỆU

28

4.2. Danh sách liên kết đơn (tt)4.2.1. Cấu trúc dữ liệu (tt) Để quản lý danh sách liên kết có thể dùng nhiều phương pháp

khác nhau, mỗi phương pháp sẽ có cấu trúc dữ liệu cụ thể. Quản lý địa chỉ phần đầu và cuối danh sách

struct List{

Node *pHead;Node *pTail;

};

info pNext pTail

pHead

Page 29: Môn: CẤU TRÚC DỮ LIỆU

29

4.2. Danh sách liên kết đơn (tt)4.2.2. Các thao tác trên danh sách liên kết đơna. Khởi tạo danh sách SLLb. Tạo mới 1 phần tử (nút) trong danh sách SLLc. Thêm 1 phần tử vào danh sách SLL Thêm vào đầu | cuối | giữa danh sách liên kết đơnd. Duyệt qua các nút trong danh sáche. Tìm kiếm phần tử trong danh sáchf. Hủy bỏ 1 phần tử trong danh sáchg. Hủy danh sáchh. Tạo mới danh sách/Nhập danh sáchi. Tách 1 danh sách thành nhiều danh sáchj. Nhập nhiều danh sách thành 1 danh sáchk. Sắp xếp thứ tự các phần tử trong danh sáchh. Sao chép 1 danh sách

Page 30: Môn: CẤU TRÚC DỮ LIỆU

30

4.2. Danh sách liên kết đơn (tt)4.2.2.a. Khởi tạo danh sách SLL Thao tác khởi tạo danh sách liên kết đơn là cho giá trị con trỏ

quản lý địa chỉ đầu của danh sách về con trỏ NULL. Hàm khởi tạo danh sách liên kết đơn:

void Khoitao(Node *pHead){

pHead = NULL;return;

}

Page 31: Môn: CẤU TRÚC DỮ LIỆU

31

4.2. Danh sách liên kết đơn (tt)

4.2.2. b. Tạo mới 1 phần tử (nút) trong danh sách SLLGiả sử tạo mới 1 phần tử có thành phần dữ liệu =x

Thuật toánB1: p = new Node //cấp phát bộ nhớ cho con trỏ p

B2: IF(p == NULL) // cấp phát không thành công

Thực hiện BKTB3: p->info=x;B4: p->pNext=NULLBKT: Kết thúc

Page 32: Môn: CẤU TRÚC DỮ LIỆU

32

4.2. Danh sách liên kết đơn (tt)4.2.2. b. Tạo mới 1 phần tử (nút) trong danh sách SLL (tt)Cài đặtNode* TaoPT(int x){ Node *p;

p=new Node;if (p==NULL)

{ cout<<"Khong du bo nho";exit(1);

}cout<<"\nMoi nhap vao so x = ";cin>>x;p->Info=x;p->pNext=NULL;return p;

}

Page 33: Môn: CẤU TRÚC DỮ LIỆU

33

4.2. Danh sách liên kết đơn (tt)4.2.2.c. Thêm 1 phần tử vào danh sách SLL (Thêm đầu DS)Thuật toán

Gỉa sử ta muốn thêm phần tử p vào đầu DS:Nếu DS rỗng thì:

pHead=p;pTail=pHead; // pTail=new_element

Ngược lại:p->pNext=pHead; pHead=p;

Page 34: Môn: CẤU TRÚC DỮ LIỆU

34

4.2. Danh sách liên kết đơn (tt)4.2.2.c. Thêm 1 phần tử vào danh sách SLL (Thêm đầu DS) (tt)Cài đặt

void Themdau(List &l, Node *p)

{

if (l.pHead==NULL)

{

l.pHead=p;

l.pTail=p;

}

else

{ p->pNext=l.pHead;

l.pHead=p;

}

}

Page 35: Môn: CẤU TRÚC DỮ LIỆU

35

4.2. Danh sách liên kết đơn (tt)4.2.2.c. Thêm 1 phần tử vào danh sách SLL (Thêm đầu DS) (tt)

x

pHead

pTail

2

1

p

Page 36: Môn: CẤU TRÚC DỮ LIỆU

36

4.2. Danh sách liên kết đơn (tt)

4.2.2.c. Thêm 1 phần tử vào danh sách SLL (tt) (Thêm giữa DS)

Thêm phần tử mới vào ngay sau phần tử qThuật toán

Nếu q!=NULL;B1: p->pNext=q->pNext;B2: q->pNext=p

Ngược lại: thêm vào đầu DS

Page 37: Môn: CẤU TRÚC DỮ LIỆU

37

4.2. Danh sách liên kết đơn (tt)4.2.2.c. Thêm 1 phần tử vào danh sách SLL (Thêm giữa DS) (tt)

Cài đặt:

void Themgiua(List &l, Node *q, int x)

{

Node *p=GetNode(x);

if (p==NULL) exit(1);

if (q!=NULL)

{

p->pNext=q->pNext;

q->pNext=p;

if (q==l.pTail)

l.pTail=p;

}

else

Themdau(l, p);

}

Page 38: Môn: CẤU TRÚC DỮ LIỆU

38

4.2. Danh sách liên kết đơn (tt)4.2.2.c. Thêm 1 phần tử vào danh sách SLL (Thêm cuối DS)Thuật toán:Nếu DS rỗng thì:

B1: pHead=p;B2: pTail=pHead;

Ngược lại:pTail->pNext=p;pTail=p;

Page 39: Môn: CẤU TRÚC DỮ LIỆU

39

4.2. Danh sách liên kết đơn (tt)4.2.2.c. Thêm 1 phần tử vào danh sách SLL (Thêm cuối DS) (tt)Cài đặt

void InsertTail(List &l, Node *p)

{

if (l.pHead==NULL)

{ l.pHead=p;

l.pTail=p;

}

else

{

l.pTail->pNext=p;

l.pTail=p;

}

}

Page 40: Môn: CẤU TRÚC DỮ LIỆU

40

4.2. Danh sách liên kết đơn (tt)4.2.2.d. Duyệt qua các nút trong danh sách liên kết đơn Là thao tác thường dùng trong các loại danh sách. Tùy theo từng trường hợp cụ thể để xử lý trong khi duyệt DS.Thuật toán:B1: p = pHeadB2: IF (p == NULL)

Thực hiện BKTB3: OutputData(p->info)B4: p = p->pNextB5: Lặp lại B2BKT: Kết thúc

Page 41: Môn: CẤU TRÚC DỮ LIỆU

41

4.2. Danh sách liên kết đơn (tt)4.2.2.d. Duyệt qua các nút trong danh sách liên kết đơn (tt)Cài đặt:

void DuyetDS(List l)

{ Node *p;

p = l.pHead;

while (p!=NULL)

{

cout<<p->Info<<" ";

p=p->pNext;

}

}

Page 42: Môn: CẤU TRÚC DỮ LIỆU

42

4.2. Danh sách liên kết đơn (tt)4.2.2.e. Tìm kiếm phần tử trong danh sách Giả sử cần tìm kiếm trong danh sách liên kết đơn phần tử có

phần dữ liệu X. Dùng thuật toán tìm tuyến tính.

Thuật toán

B1: p=pHead

B2: IF(p== NULL OR p->info == X)

Thực hiện BKT

B3: p = p->pNext

B4: Lặp lại B2

BKT: Kết thúc

Page 43: Môn: CẤU TRÚC DỮ LIỆU

43

4.2. Danh sách liên kết đơn (tt)4.2.2.e. Tìm kiếm phần tử trong danh sách (tt)Cài đặt

Node* Timkiem(List l, int x)

{ Node *p;

p=l.pHead;

while ((p!=NULL) && (p->Info!=x))

p=p->pNext;

return p;

}

Page 44: Môn: CẤU TRÚC DỮ LIỆU

44

4.2. Danh sách liên kết đơn (tt)

4.2.2.f. Xoá 1 phần tử trong danh sáchXoá đầu DS Thuật toán:Nếu (PHead !=NULL) thì:

B1: p=pHead;B2: pHead=pHead->pNext

free(p);B3: Nếu pHead=NULL thì pTail= NULL

Page 45: Môn: CẤU TRÚC DỮ LIỆU

45

4.2. Danh sách liên kết đơn (tt)4.2.2.f. Xoá1 phần tử trong danh sáchXoá đầu DS Cài đặt:void Xoadau(List &l) // xoa phan tu{

p=new Node;p=l.pHead;if (p!=NULL)

{l.pHead=l.pHead->pNext;delete(p);}

if (l.pHead==NULL)l.pTail=NULL;

}

Page 46: Môn: CẤU TRÚC DỮ LIỆU

46

4.2. Danh sách liên kết đơn (tt)

4.2.2.f. Xoá1 phần tử trong danh sáchXoá phần tử ngay sau phần tử q:Thuật toán:

nếu q!=NULL thìB1: p=q->pNext; //p là phần tử cần huỷB2: nếu (p!=NULL) thì //q không phải cuối DS

B21: q->pNext=p->pNext;B22: free(p); //xoá biến

Page 47: Môn: CẤU TRÚC DỮ LIỆU

47

4.2. Danh sách liên kết đơn (tt)4.2.2.f. Xoá1 phần tử trong danh sáchXoá phần tử ngay sau phần tử q:

void XoaPT(List &l, Node *q){

if (q!=NULL){

p=q->pNext;// p la phan tu can xoaif (p!=NULL)

if(p==l.pTail){ l.pTail=q;

free(p);}else{q->pNext=p->pNext;free(p);}

}}

Page 48: Môn: CẤU TRÚC DỮ LIỆU

48

4.2. Danh sách liên kết đơn (tt)

4.2.2.f. Xoá1 phần tử trong danh sáchXoá phần tử có khoá k:Thuật toán:B1: Tìm phần tử p có khoá k và phần tử q đứng trước

nóB2: Nếu (p!=NULL) thì //tìm thấy k

Xoá p ra khỏi DSNgược lại:

Báo không có k;

Page 49: Môn: CẤU TRÚC DỮ LIỆU

49

4.2. Danh sách liên kết đơn (tt)4.2.2.f. Xoá1 phần tử trong danh sáchXoá phần tử có khoá k:Cài đặt:int XoaptK(List &l,int k) // xoa phan tu{

Node *p=l.pHead;Node *q=NULL;while (p!=NULL)

{ if(p->info==k) break;q=p; p=p->pNext;

}If(p==NULL) Return (0); //không tìm thấyif(q!=NULL){ if(p==l.pTail)

l.pTail=q;q->pNext=p->pNext;delete p;

}

Page 50: Môn: CẤU TRÚC DỮ LIỆU

50

4.2. Danh sách liên kết đơn (tt)4.2.2.f. Xoá1 phần tử trong danh sáchXoá phần tử có khoá k:Cài đặt: (tt)

else

{

l.pHead=p->pNext;

if(l.pHead==NULL)

l.pTail=NULL;

}

Return (1);

}

Page 51: Môn: CẤU TRÚC DỮ LIỆU

51

4.2. Danh sách liên kết đơn (tt)

4.2.2.g. Hủy danh sách Việc hủy danh sách thực chất là thực hiện nhiều lần

hủy 1 nútThuật toán:B1: Trong khi DS chưa hết

p=pHead;pHead=pHead->pNext;

B2: Huỷ pB3: pTail=NULL;

Page 52: Môn: CẤU TRÚC DỮ LIỆU

52

4.2. Danh sách liên kết đơn (tt)4.2.2.g. Hủy danh sách (tt)Cài đặt thuật toán:void XoaDs (List &l){

while (l.pHead!= NULL){

p = l.pHead;l.pHead = p->pNext;delete (p);

}l.pTail=NULL;

}

Page 53: Môn: CẤU TRÚC DỮ LIỆU

53

4.2. Danh sách liên kết đơn (tt)4.2.2.h. Tạo mới danh sách/Nhập danh sách Tạo mới 1 danh sách thực chất là liên tục thêm 1 phần tử vào

danh sách mà danh sách ban đầu là rỗng. Tạo DS bằng cách thêm vào đầu DS

void TaoDSdau(List &l, int x)

{

for (int i=0;i<8;i++) // nen dung vong lap do while de viet

{

TaoPT(x);

Themdau(l,p);

}

}

Page 54: Môn: CẤU TRÚC DỮ LIỆU

54

4.2. Danh sách liên kết đơn (tt)

Tạo DS bằng cách thêm vào cuối DS

void TaoDScuoi(List &l, int x)

{

for (int i=0;i<1;i++)

{

TaoPT(x);

Themcuoi(l,p);

}

}

Page 55: Môn: CẤU TRÚC DỮ LIỆU

55

4.2. Danh sách liên kết đơn (tt)4.2.2.i. Tách 1 danh sách thành nhiều danh sách

Page 56: Môn: CẤU TRÚC DỮ LIỆU

56

4.2. Danh sách liên kết đơn (tt)4.2.2.j. Nhập nhiều danh sách thành 1 danh sách

Page 57: Môn: CẤU TRÚC DỮ LIỆU

57

4.2. Danh sách liên kết đơn (tt)4.2.2.k. Sắp xếp thứ tự các phần tử trong danh sáchThuật toán sắp xếp trộn tự nhiên:B1: IF (SLLSplit(SLList, TempList) == NULL)Thực hiện BKT B2: SLLMerge(SLList, TempList, SLList)B3: Lặp lại B1BKT: Kết thúc void SLLNaturalMergeSort(SLLType &SList){ SLLType TempList = NULL, List = NULL;

while (SLLSplit(SList,TempList) != NULL){ SLLMerge(SList, TempList, List);

SList = List;}return;

}

Page 58: Môn: CẤU TRÚC DỮ LIỆU

58

4.2. Danh sách liên kết đơn (tt)4.2.2.h. Sao chép 1 danh sách Sao chép 1 danh sách thực chất là tạo mới danh sách

NewList bằng cách duyệt qua các nút của SLList để lấy thành phần dữ liệu để tạo thành 1 nút mới & bổ sung nút mới này vào danh sách NewList.

Thuật toánB1: NewList = NULLB2: CurrNode = SLListB3: IF (CurNode = NULL) Thực hiện BKTB4: SLLAddLast(NewList, CurrNode->Key)B5: CurrNode = CurrNode->NextNodeB6: Lặp lại B3BKT: Kết thúc

Page 59: Môn: CẤU TRÚC DỮ LIỆU

59

4.2. Danh sách liên kết đơn (tt)4.2.2.h. Sao chép 1 danh sách (tt)Cài đặt thuật toán:SLLType SLLCopy(SLLType SList, SLLType &NewList){ NewList = NULL;

SLLType CurrNode = SList;while (CurrNode != NULL){ SLLType NewNode=SLLAddLast(NewList,CurrNode->Key);

if (NewNode == NULL){ SLLDelete(NewList);

break;}

}return (NewList);

}

Page 60: Môn: CẤU TRÚC DỮ LIỆU

60

4.3. Danh sách liên kết đôi (DLL) Các phần tử của danh sách liên kết đôi có 2 mối liên kết với

các phần tử khác trong danh sách. Cấu trúc dữ liệu của danh sách liên kết đôi:typedef struct DLLNode{ T Key;

InfoType Info;DLLNode * NextNode;DLLNode * PreNode;

} DLLOneNode;typedef struct DLLNode{ T Key;

DLLNode * NextNode;DLLNode * PreNode;

} DLLOneNode;typedef DLLOneNode * DLLType;

Page 61: Môn: CẤU TRÚC DỮ LIỆU

61

4.3. Danh sách liên kết đôi (tt)4.3.1. Quản lý danh sách liên kết liên kết đôi: Quản lý địa chỉ phần tử đầu của danh sáchDLLType DLList1 Quản lý địa chỉ phần tử đầu và phần tử cuối của danh sáchtypedef struct DLLPairNode{ DLLType DLLFirst;

DLLType DLLLast;} DLLPType;DLLPType DLList2; Quản lý địa chỉ phần tử đầu, phần tử cuối và số phần tử của

danh sáchtypedef struct DLLPairNode{ DLLType DLLFirst;

DLLType DLLLast;unsigned NumNode;

} DLLPNType;DLLPNType DLList3;

Page 62: Môn: CẤU TRÚC DỮ LIỆU

62

4.3. Danh sách liên kết đôi (tt)4.3.2. Thao tác trên danh sách liên kết đôia. Khởi tạo danh sách liên kết đôib. Tạo mới 1 phần tửc. Thêm 1 phần tử vào danh sáchd. Duyệt qua các nút trong 1 danh sáche. Tìm kiếm 1 phần tử trong danh sáchf. Loại bỏ 1 phần tử trong danh sáchg. Hủy toàn bộ danh sáchh. Tạo 1 danh sách mới/Nhập danh sáchi. Tách 1 danh sách thành nhiều danh sáchj. Nhập nhiều danh sách thành 1 danh sáchk. Sắp xếp thứ tự thành phần dữ liệu trong danh sáchl. Sao chép 1 danh sách thành 1 danh sách mới

Page 63: Môn: CẤU TRÚC DỮ LIỆU

63

4.3. Danh sách liên kết đôi (tt)

4.3.2.a. Khởi tạo danh sách liên kết đôi

Cho giá trị các con trỏ quản lý địa chỉ 2 nút đầu và cuối danh sách liên kết đôi về NULL

DLLPType DLLInitialize(DLLPType &DList)

{

DList.DLLFirst = NULL;

DList.DLLast = NULL;

return (DList);

}

Page 64: Môn: CẤU TRÚC DỮ LIỆU

64

4.3. Danh sách liên kết đôi (tt)4.3.2.b. Tạo mới 1 phần tửTạo nút mới có thành phần dữ liệu là NewDataThuật toánB1: Dnode = New DLLOneNodeB2: IF (Dnode == NULL)

Thực hiện BKTB3: DNode ->NextNode = NULLB4: DNode ->Key = NewDataB5: DNode ->PreNode = NULLBKT: Kết thúc DLLType DLLCreateNode(T NewData){ DLLType Pnode = new DLLOneNode;

if (Pnode != NULL){ Pnode ->NextNode = NULL;

Pnode ->Key = NewDataPnode ->PreNode = NULL;

}return (Pnode);

}

Page 65: Môn: CẤU TRÚC DỮ LIỆU

65

4.3. Danh sách liên kết đôi (tt)4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm đầu)B1: NewNode = DLLCreateNode(NewData)B2: IF (NewNode == NULL)

Thực hiện BKTB3: IF(DLLList.DLLFirst == NULL)

B3.1: DLLList.DLLFirst = NewNodeB3.2: DLLList.DLLLast = NewNodeB3.3: Thực hiện BKT

B4: NewNode ->NextNode = DLLList.DLLFirstB5: DLLList.DLLFirst ->PreNode = NewNode// chuyển vai trò đứng đầu của NewNode cho DLLFirstB6: DLLList.DLLFirst = NewNodeBKT: Kết thúc

Page 66: Môn: CẤU TRÚC DỮ LIỆU

66

4.3. Danh sách liên kết đôi (tt)4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm đầu)DLLType DLLAddFirst(DLLPType &DList, T NewData){

DLLType NewNode = DLLCreateNode(NewData);if (NewNode == NULL)

return (NULL);if (DList.DLLFirst == NULL)

DList.DLLFirst = DList.DLLLast = NewNode;else{

NewNode ->NextNode = DList.DLLFirst; DList.DLLFirst ->PreNode = NewNode; DList.DLLFirst = NewNode;

}return (NewNode);

}

Page 67: Môn: CẤU TRÚC DỮ LIỆU

67

4.3. Danh sách liên kết đôi (tt)4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm cuối)B1: NewNode = DLLCreateNode(NewData)B2: IF (NewNode == NULL)

Thực hiện BKTB3: IF(DLLList.DLLFirst == NULL)

B3.1: DLLList.DLLFirst = NewNodeB3.2: DLLList.DLLLast = NewNodeB3.3: Thực hiện BKT

B4: DLLList.DLLLast ->NextNode = NewNode B5: NewNode ->PreNode = DLLList.DLLLast

// chuyển vai trò đứng đầu của NewNode cho DLLFirstB6: DLLList.DLLLast = NewNodeBKT: Kết thúc

Page 68: Môn: CẤU TRÚC DỮ LIỆU

68

4.3. Danh sách liên kết đôi (tt)4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm cuối)DLLType DLLAddLast(DLLPType &DList, T NewData){

DLLType NewNode = DLLCreateNode(NewData);if (NewNode == NULL)

return (NULL);if (DList.DLLLast == NULL)

DList.DLLFirst = DList.DLLLast = NewNode;else{

DList.DLLLast ->NextNode = NewNode; NewNode ->PreNode = DList.DLLLast;DList.DLLLast = NewNode;

}return (NewNode);

}

Page 69: Môn: CẤU TRÚC DỮ LIỆU

69

4.3. Danh sách liên kết đôi (tt)4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm giữa)B1: IF (InsNode ->NextNode == NULL)

B1.1: DLLAddLast(DLLList, NewData)B1.2: Thực hiện BKT

B2: NewNode = DLLCreateNode(NewData)B3: IF (NewNode == NULL)

Thực hiện BKT

B4: NewNode ->NextNode = InsNode ->NextNode B5: InsNode ->NextNode ->PreNode = NewNode

B6: InsNode ->NextNode = NewNodeB7: NewNode ->PreNode = InsNodeBKT: Kết thúc

Page 70: Môn: CẤU TRÚC DỮ LIỆU

70

4.3. Danh sách liên kết đôi (tt)4.3.2.c. Thêm 1 phần tử vào danh sách (Thêm giữa)DLLType DLLAddMid(DLLPType &DList, T NewData, DLLType

&InsNode){ DLLType NewNode = DLLCreateNode(NewData);

if (NewNode == NULL)return (NULL);

if (InsNode ->NextNode == NULL){ InsNode ->NextNode = NewNode;

NewNode ->PreNode = InsNode;DList.DLLLast = NewNode;

}else{ NewNode ->NextNode = InsNode ->NextNode;

InsNode ->NextNode ->PreNode = NewNode;InsNode ->NextNode = NewNode;NewNode ->PreNode = InsNode;

}return (NewNode);

}

Page 71: Môn: CẤU TRÚC DỮ LIỆU

71

4.3. Danh sách liên kết đôi (tt)4.3.2.d. Duyệt qua các nút trong 1 danh sáchThuật toánB1: CurrNode = DLLList.FirstB2: IF (CurrNode == NULL)

Thực hiện BKTB3: OutputData(CurrNode->Key)B4: CurrNode = CurrNode ->NextNodeB5: Lặp lại B2BKT: Kết thúcCài đặt thuật toánvoid DLLTravelling (DLLPType DList) { DLLType CurrNode = DList.DLLFirst;

while (CurrNode != NULL){ OutputData(CurrNode->Key);

CurrNode = CurrNode ->NextNode ;}return;

}

Page 72: Môn: CẤU TRÚC DỮ LIỆU

72

4.3. Danh sách liên kết đôi (tt)4.3.2.e. Tìm kiếm 1 phần tử trong danh sáchThuật toánB1: CurrNode = DLLList.FirstB2: IF (CurrNode == NULL OR CurrNode->Key = SearchData)

Thực hiện BKTB3: CurrNode = CurrNode ->NextNodeB4: Lặp lại B2BKT: Kết thúcCài đặt thuật toánDLLType DLLSearching(DLLPType Dlist, T SearchData){ DLLType CurrNode = DList.DLLFirst;

while (CurrNode != NULL){ if (CurrNode->Key == SearchData)

break;CurrNode = CurrNode ->NextNode

}return (CurrNode);

}

Page 73: Môn: CẤU TRÚC DỮ LIỆU

73

4.3. Danh sách liên kết đôi (tt)4.3.2.f. Loại bỏ 1 phần tử trong danh sáchThuật toánB1: DelNode = DLLSearching(DLLList. DelData) // Tìm kiếm nút DelDataB2: IF(DelNode == NULL)

Thực hiện BKTB3: IF(DelNode->PreNode=NULL AND DelNode->NextNode=NULL)

B3.1: DLLList.DLLFirst = DLLList.DLLLast = NULLB3.2: Thực hiện B8

B4: IF (DelNode ->PreNode = NULL) // Loại nút đầu tiên trong DSB4.1: DLLList.DLLFirst = DLLList.DLLFirst ->NextNode B4.2: DLLList.DLLFirst ->PreNode = NULLB4.3: Thực hiện B8

B5: IF (DelNode ->NextNode = NULL) // Loại nút cuối trong DSB4.1: DLLList.DLLLast = DLLList.DLLLast ->PreNode B4.2: DLLList.DLLLast ->NextNode = NULLB4.3: Thực hiện B8

// Liên kết giữa nút trước và sau nút bị xóaB6: DelNode ->PreNode ->NextNode = DelNode ->NextNode B7: DelNode ->NextNode ->PreNode = DelNode ->PreNode // Bỏ mối liên kết giữa DelNode giữa 2 nút trước & sauB8: DelNode ->NextNode = DelNode ->PreNode = NULLB9: delete DelNodeBKT: Kết thúc

Page 74: Môn: CẤU TRÚC DỮ LIỆU

74

4.3. Danh sách liên kết đôi (tt)4.3.2.f. Loại bỏ 1 phần tử trong danh sáchCài đặt thuật toánInt DLLDeleteNode (DLLPType &DList, T DelData){ DLLType DelNode = DLLSearching(DList, DelData)

if (DelNode == NULL)return (-1);

if (DelNode ->NextNode == NULL && DelNode ->PreNode == NULL)DList.DLLFirst = DList.DLLLast = NULL;

elseif (DelNode ->PreNode ==NULL){ DList.DLLFirst = Dist.DLLFirst ->NextNode ;

Dist.DLLFirst ->PreNode = NULL;}else

if (DelNode ->NextNode ==NULL){ DList.DLLLast = Dist.DLLLast ->PreNode ; Dist.DLLLast ->NextNode = NULL;}else{ DelNode ->PreNode ->NextNode = DelNode -

>NextNode; DelNode ->NextNode ->PreNode = DelNode -

>PreNode ;}

}

Page 75: Môn: CẤU TRÚC DỮ LIỆU

75

4.3. Danh sách liên kết đôi (tt)4.3.2.g. Hủy toàn bộ danh sáchThực hiện nhiều lần thao tác hủy một nútThuật toánB1: IF (DLLList.DLLFirst == NULL)

Thực hiện BKTB2: TempNode = DLLList.DLLFirstB3: DLLList.DLLFirst = DLLList.DLLFirst ->NextNode B4: IF (DLLList.DLLFirst == NULL)

B4.1: DLLList.DLLLast = NULLB4.2: Thực hiện B7

B5: DLLList.DLLFirst ->PreNode = NULLB6: TempNode ->NextNode = NULLB7: delete TempNodeB8: Lặp lại B1BKT: Kết thúc

Page 76: Môn: CẤU TRÚC DỮ LIỆU

76

4.3. Danh sách liên kết đôi (tt)4.3.2.g. Hủy toàn bộ danh sách (tt)Cài đặt thuật toánvoid DLLDelete (DLLPType &DList){

DLLType TempNode = DList.DLLFirst;while (TempNode != NULL){

DList.DLLFirst = DList.DLLFirst ->NextNode;TempNode ->NextNode = NULL;if (DList.DLLFirst != NULL)

DList.DLLFirst ->PreNode = NULL;delete TempNode;TempNode = DList.DLLFirst;

}return;

}

Page 77: Môn: CẤU TRÚC DỮ LIỆU

77

4.3. Danh sách liên kết đôi (tt)4.3.2.h. Tạo 1 danh sách mới/Nhập danh sách

Thuật toánB1: DLLInitialize(DLLList)B2: I = 1B3: IF (I >N)

Thực hiện BKTB4: NewData = InputNewData();B5: DLLAddLast(DLLList, NewData) B6: I++B7: Lặp lại B3BKT: Kết thúc

Page 78: Môn: CẤU TRÚC DỮ LIỆU

78

4.3. Danh sách liên kết đôi (tt)4.3.2.h. Tạo 1 danh sách mới/Nhập danh sách

Cài đặt thuật toánDLLPType DLLCreate (DLLPType &DList, int N){

DLLInitialize(DList);T NewData;for (int i=0; i <N; i++){

NewData = InputNewData();if (DLLAddLast(DList, NewData) == NULL){ DLLDelete(DList);

break;}

}return (DList);

}

Page 79: Môn: CẤU TRÚC DỮ LIỆU

79

4.3. Danh sách liên kết đôi (tt)4.3.2.i. Tách 1 danh sách thành nhiều danh sách

Page 80: Môn: CẤU TRÚC DỮ LIỆU

80

4.3. Danh sách liên kết đôi (tt)4.3.2.j. Nhập nhiều danh sách thành 1 danh sách

Page 81: Môn: CẤU TRÚC DỮ LIỆU

81

4.3. Danh sách liên kết đôi (tt)4.3.2.k. Sắp xếp thứ tự thành phần dữ liệu trong danh sáchB1: Inode = DLLList.DLLFirstB2: IF(Inode == NULL)

Thực hiện BKTB3: IF (Inode == DLLList.DLLLast)

Thực hiện BKTB4: Jnode = DLLList.DLLLastB5: IF (Jnode = Inode)

Thực hiện B7B6: ELSE

B6.1: If (Jnode->Key < Jnode ->PreNode ->Key)Swap (Jnode ->Key, Jnode ->PreNode ->Key)

B6.2: Jnode = Jnode ->NextNode B6.3: Lặp lại B5

B7: Inode = Inode ->NextNode B8: Lặp lại B3BKT: Kết thúc

Page 82: Môn: CẤU TRÚC DỮ LIỆU

82

4.3. Danh sách liên kết đôi (tt)4.3.2.k. Sắp xếp thứ tự thành phần dữ liệu trong danh sách (tt)Cài đặt thuật toánvoid DLLBubbleSort (DLLPType &DList){ DLLType Inode = DList.DLLFirst;

if (Inode == NULL)return;

while (Inode != DList.DLLLast){ DLLType Jnode = DList.DLLLast;

while (Jnode != Inode){ if (Jnode->Key < Jnode ->PreNode ->Key)

Swap(Jnode->Key,Jnode->PreNode->Key)

Jnode = Jnode ->PreNode ;}Inode = Inode ->NextNode ;

}return;

}

Page 83: Môn: CẤU TRÚC DỮ LIỆU

83

4.3. Danh sách liên kết đôi (tt)4.3.2.l. Sao chép 1 danh sách thành 1 danh sách mới

Thuật toánB1: DLLInitialize(NewList)B2: CurrNode = DLLList.DLLFirstB3: IF (CurrNode == NULL)

Thực hiện BKTB4: DLLAddLast(NewList, CurrNode->Key)B5: CurrNode = CurrNode ->NextNode B6: Lặp lại B3BKT: Kết thúc

Page 84: Môn: CẤU TRÚC DỮ LIỆU

84

4.3. Danh sách liên kết đôi (tt)4.3.2.l. Sao chép 1 danh sách thành 1 danh sách mới

Cài đặt thuật toánDLLPType DLLCopy(DLLPType &DList, DLLPType &NewList){

DLLInitialize(NewList);DLLType CurrNode = DList.DLLFirst;while (CurrNode != NULL){

if (DLLAddLast(NewList, CurrNode->Key) == NULL){ DLLDelete(NewList);

break;}CurrNode = CurrNode ->NextNode ;

}return (NewList);

}

Page 85: Môn: CẤU TRÚC DỮ LIỆU

85

4. Danh sách liên kết4.4. Ưu nhược điểm của danh sách liên kết Nhược điểm

Mật độ sử dụng bộ nhớ của danh sách liên kết không tối ưu tuyệt đối (<100%)

Việc truy xuất và tìm kiếm các phần tử trong danh sách liên kết mất nhiều thời gian vì phải duyệt tuần tự qua các phần tử trong danh sách.

Bộ nhớ cần nhiều vì phải lưu thêm phần tử liên kết, nếu vùng dữ liệu là lớn thì tỷ lệ mức sử dụng bộ nhớ là cao.

Ưu điểm Tận dụng được không gian bộ nhớ nhỏ để lưu trữ từng nút. Việc thêm, xóa phần tử trong danh sách liên kết là dễ

dàng, chỉ cần thay đổi mối liên kết của các phần tử với nhau.

Page 86: Môn: CẤU TRÚC DỮ LIỆU

86

5. Danh sách hạn chế

5.1. Hàng đợi (Queue)

5.2. Ngăn xếp (Stack)

5.3. Ứng dụng của danh sách hạn chế

Page 87: Môn: CẤU TRÚC DỮ LIỆU

87

5. Danh sách hạn chế

5.1. Hàng đợi (Queue) Hàng đợi là một danh sách mà trong đó thao tác thêm 1 phần

tử vào trong danh sách được thực hiện 1 đầu này và lấy 1 phần tử trong danh sách lại thực hiện bởi đầu kia.

Các phần tử đưa vào trong hàng đợi trước sẽ được lấy ra trước, phần tử đưa vào trong hàng đợi sau sẽ được lấy ra sau.

Hàng đợi còn được gọi là danh sách FIFO List và cấu trúc dữ liệu này còn được gọi cấu trúc FIFO (First In First Out)

Có nhiều cách biểu diễn hàng đợi: dùng danh sách đặc hoặc dùng danh sách liên kết

Quản lý vị trí 2 đầu của hàng đợi thông qua 2 biến: Biến trước (Font) Biến sau (Rear)

Page 88: Môn: CẤU TRÚC DỮ LIỆU

88

5.1. Hàng đợi (tt)

5.1.1. Cấu trúc dữ liệu biểu diễn cho hàng đợi Biểu diễn và tổ chức hàng đợi bằng danh sách đặc và danh

sách liên kết đơn được quản lý bởi 2 phần tử đầu và cuối Cấu trúc dữ liệu biểu diễn hàng đợi bằng danh sách đặc

typedef struct QC

{ int Len;

int Front, Rear;

T * List;

} CQUEUE;

CQUEUE CQList;

Page 89: Môn: CẤU TRÚC DỮ LIỆU

89

5.1. Hàng đợi (tt)

5.1.1. Cấu trúc dữ liệu biểu diễn cho hàng đợi (tt)

Cấu trúc dữ liệu biểu diễn hàng đợi bằng danh sách liên kết

typedef struct QElement

{ T Key;

QElement *Next;

} QOneElement;

typedef QElement *QType;

typedef struct QPElement

{ QType Font;

QType Rear;

} SQUEUE;

SQUEUE SQList;

Page 90: Môn: CẤU TRÚC DỮ LIỆU

90

5.1. Hàng đợi (tt)

5.1.2. Các thao tác trên hàng đợi tổ chức bằng danh sách đặc

a. Khởi tạo hàng đợi (Initialize)

b. Thêm 1 phần tử vào hàng đợi (Add)

c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (Get)

d. Hủy hàng đợi

Page 91: Môn: CẤU TRÚC DỮ LIỆU

91

5.1. Hàng đợi (tt)

5.1.2.a. Khởi tạo hàng đợi (tổ chức bằng danh sách đặc)

B1: CQList.Len = Length

B2: CQList.List = new T[Length]

B3: IF(CQList.List == NULL)

Thực hiện BKT

B4: CQList.Front = CQList.Rear = 0

BKT: Kết thúc

Page 92: Môn: CẤU TRÚC DỮ LIỆU

92

5.1. Hàng đợi (tt)

5.1.2.a. Khởi tạo hàng đợi (tổ chức bằng danh sách đặc)

Cài đặt thuật toán

T * CQInitialize (CQUEUE & QList, int Length)

{

QList.Len = Length;

QList.List = new T[Length];

if (QList.List == NULL)

return (NULL);

QList.Front = QList.Rear =-1;

return (QList.List);

}

Page 93: Môn: CẤU TRÚC DỮ LIỆU

93

5.1. Hàng đợi (tt)5.1.2.b. Thêm 1 phần tử vào hàng đợi (tổ chức bằng danh sách

đặc)Thuật toán// nếu hàng đợi đã bị đầyB1: IF(CQList.Front ==1 AND CQList.Rear == CQList.Len)

Thực hiện BKTB2: IF(CQList.Rear+1 == CQList.Front)

Thực hiện BKTB3: IF(CQList.Front = 0) // nếu hàng đợi rỗng

CQList.Front = 1B4: IF(CQList.Rear = CQList.Len)

CQList.Rear = 1B5: ELSE

CQList.Rear ++B6: CQList.List[CQList.Rear] = NewDataBKT: Kết thúc

Page 94: Môn: CẤU TRÚC DỮ LIỆU

94

5.1. Hàng đợi (tt)5.1.2.b. Thêm 1 phần tử vào hàng đợi (tổ chức bằng danh sách

đặc)Cài đặt thuật toánint CQAdd(CQUEUE & QList, T NewData){ if (QList.Front == 0 && QList.Rear == QList.Len -1)

return (-1);if (QList.Rear +1 == QList.Front)

return (-1);if (QList.Front == -1)

QList.Front =0if (QList.Rear == QList.Len)

QList.Rear = 0;else

QList.Rear += 1;QList.List[QList.Rear] = NewDatareturn (QList.Rear );

}

Page 95: Môn: CẤU TRÚC DỮ LIỆU

95

5.1. Hàng đợi (tt)5.1.2.c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (tổ

chức bằng danh sách đặc)B1: IF (CQList.Front = 0)

Thực hiện BKTB2: Data = CQList.List[CQList.Front]B3: IF(CQList.Rear == CQList.Front)

B3.1: CQList.Rear = CQList.Front = 0B3.2: Thực hiện BKT

B4: IF (CQList.Front = CQList.Len)CQList.Front = 1

B5: ELSECQList.Front++

BKT: Kết thúc

Page 96: Môn: CẤU TRÚC DỮ LIỆU

96

5.1. Hàng đợi (tt)5.1.2.c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (tổ chức

bằng danh sách đặc)Cài đặt thuật toánint CQGet(CQUEUE & QList, T &Data){ if (QList.Front == -1)

return (-1);Data = QList.List[QList.Front];if (QList.Front == QList.Rear){ QList.Front = QList.Rear = -1;

return (1);}if (QList.Front == QList.Len -1)

QList.Front = 0;else

QList.Front += 1;return (1);

}

Page 97: Môn: CẤU TRÚC DỮ LIỆU

97

5.1. Hàng đợi (tt)

5.1.2.d. Hủy hàng đợi (tổ chức bằng danh sách đặc)

Hủy bộ nhớ cấp phát cho hàng đợi

void CQDelete(CQUEUE & QList)

{

delete QList.List;

return;

}

Page 98: Môn: CẤU TRÚC DỮ LIỆU

98

5.1. Hàng đợi (tt)

5.1.3. Các thao tác trên hàng đợi tổ chức bằng danh sách liên kết đơn

a. Khởi tạo hàng đợi (Initialize)

b. Thêm 1 phần tử vào hàng đợi (Add)

c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (Get)

d. Hủy hàng đợi

Page 99: Môn: CẤU TRÚC DỮ LIỆU

99

5.1. Hàng đợi (tt)

5.1.3.a. Khởi tạo hàng đợi (dùng danh sách liên kết đơn)

Tương tự với danh sách liên kết đơn, hàm khởi tạo thực hiện gán con trỏ Front và Rear về NULL

SQUEUE SQInitialize (SQUEUE &QList)

{

QList.Front = QList.Rear = NULL;

return (QList);

}

Page 100: Môn: CẤU TRÚC DỮ LIỆU

100

5.1. Hàng đợi (tt)5.1.3.b. Thêm 1 phần tử vào hàng đợi (dùng danh sách liên

kết đơn)Thêm phần tử vào sau phần tử Rear (Thêm vào cuối danh sách

liên kết)Giả sử dữ liệu đưa vào hàng đợi là NewDataB1: NewElement = SLLCreateNode(NewData)B2: IF (NewElement == NULL)

Thực hiện BKTB3: IF (SQList.Front == NULL) // hàng đợi dang rỗng

B3.1: SQList.Front = SQList.Rear = NewElementB3.2: Thực hiện BKT

B4: SQList.Rear->Next = NewElementB5: SQList.Rear = NewElementBKT: Kết thúc

Page 101: Môn: CẤU TRÚC DỮ LIỆU

101

5.1. Hàng đợi (tt)5.1.3.b. Thêm 1 phần tử vào hàng đợi (dùng danh sách liên kết đơn)

Cài đặt thuật toán:

QType SQAdd(SQUEUE &Qlist, T NewData)

{ QType NewElement = SLLCreateNode(NewData)

if (NewElement == NULL)

return (NULL);

if (QList.Front == NULL)

QList.Front = QList.Rear = NewElement;

else

{ QList.Rear->Next = NewElement;

QList.Rear = NewElement;

}

return(NewElement);

}

Page 102: Môn: CẤU TRÚC DỮ LIỆU

102

5.1. Hàng đợi (tt)5.1.3.c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (dùng

danh sách liên kết đơn)Lấy nội dung thành phần dữ liệu của phần tử ở địa chỉ Front ra

biến Data và tiến hành hủy phần tử nàyB1: IF (SQList.Front == NULL) // nếu hàng đợi bị rỗng

Thực hiện BKTB2: TempElement = SQList.Front;B3: SQList.Front = SQList.Front ->NextB4: TempElement ->Next = NULLB5: Data = TempElement ->KeyB6: IF (SQList.Front == NULL)

SQList.Rear == NULLB7: delete TempElementBKT: Kết thúc

Page 103: Môn: CẤU TRÚC DỮ LIỆU

103

5.1. Hàng đợi (tt)5.1.3.c. Lấy nội dung 1 phần tử trong hàng đợi ra xử lý (dùng

danh sách liên kết đơn) Cài đặt thuật toán

int SQGet (SQUEUE &QList, T &Data)

{ if (QList.Front = NULL)

return (-1);

QType TempElement = QList.Front;

QList.Front = QList.Front ->Next;

TempElement ->Next = NULL;

Data = TempElement ->Next ;

if (QList.Front = NULL)

QList.Rear = NULL;

delete TempElement;

return(1);

}

Page 104: Môn: CẤU TRÚC DỮ LIỆU

104

5.1. Hàng đợi (tt)

5.1.3.d. Hủy hàng đợi (dùng danh sách liên kết đơn)

void SQQueue (SQUEUE &QList)

{

QList.Rear = NULL;

while (QList.Front != NULL)

{

QType TempElement = QList.Front;

TempElement ->Next = NULL;

delete TempElement;

}

return;

}

Page 105: Môn: CẤU TRÚC DỮ LIỆU

105

5.2. Ngăn xếp (Stack)

Ngăn xếp là một danh sách mà trong đó thao tác trên 1 phần tử vào trong ngăn xếp và thao tác lấy ra một phần tử được thực hiện 1 đầu.

Các phần tử được đưa vào ngăn xếp sau cùng sẽ được lấy ra trước tiên, phần tử được đưa vào trước tiên sẽ được lấy ra sau cùng.

Ngăn xếp được gọi là danh sách vào sau ra trước LIFO, cấu trúc dữ liệu này được gọi là cấu trúc LIFO.

5.2.1. Cấu trúc dữ liệu

5.2.2. Các thao tác trên ngăn xếp tổ chức bằng danh sách đặc

5.2.2. Các thao tác trên ngăn xếp tổ chức bằng danh sách liên kết

Page 106: Môn: CẤU TRÚC DỮ LIỆU

106

5.2. Ngăn xếp (tt)5.2.1. Cấu trúc dữ liệuBiểu diễn và tổ chức bằng danh sách đặctypedef struct SC{ int Size;

int SP;T * List;

} CSTACK;CSTACK CSList;Biểu diễn và tổ chức bằng danh sách liên kếttypedef struct SElement{ T Key;

SElement *Next;} SOneElement;typedef struct SOneElement *SSTACK;SSTACK SSP;

Page 107: Môn: CẤU TRÚC DỮ LIỆU

107

5.2. Ngăn xếp (tt)

5.2.2. Các thao tác trên ngăn xếp tổ chức bằng danh sách đặc

5.2.2.a. Khởi tạo ngăn xếp (Initialize)

5.2.2.b. Thêm 1 phần tử vào ngăn xếp (Push)

5.2.2.c. Lấy nội dung 1 phần tử trong ngăn xếp ra xử lý (Pop)

5.2.2.d. Hủy ngăn xếp

Page 108: Môn: CẤU TRÚC DỮ LIỆU

108

5.2. Ngăn xếp (tt)5.2.2.a. Khởi tạo ngăn xếp (dùng danh sách đặc)B1: CSList.Size = MaxSizeB2: CSList.List = new T[MaxSize]B3: IF (CSList.List == NULL)

Thực hiện BKTB4: CSList.SP = CSList.Size +1BKT: Kết thúcT * CSInitialize(CSTACK &SList, int MaxSize){ SList.Size = MaxSize;

SList.List = new T[MaxSize];if (SList.List == NULL)

return (NULL);SList.SP = SList.Size ;return (SList.List);

}

Page 109: Môn: CẤU TRÚC DỮ LIỆU

109

5.2. Ngăn xếp (tt)5.2.2.b. Thêm 1 phần tử vào ngăn xếp (dùng danh sách đặc)B1: IF (CSList.SP == 1)

Thực hiện BKTB2: CSList.SP --B3: CSList.List[CSList.SP] = NewData BKT: Kết thúcint CSPush(CSTACK &SList, T NewData){ if (SList.SP == 0)

return (-1);SList.SP -= 1;SList.List[SList.SP] = NewData;return (SList.SP);

}

Page 110: Môn: CẤU TRÚC DỮ LIỆU

110

5.2. Ngăn xếp (tt)5.2.2.c. Lấy nội dung 1 phần tử trong ngăn xếp ra xử lý (dùng danh

sách đặc)

B1: IF (CSList.SP == CSList.Size +!)

Thực hiện BKT

B2: Data = CSList.List[CSList.SP]

B3: CSList.SP++

BKT: Kết thúc

int CSPop(CSTACK &SList, T &Data)

{ if (SList.SP == SList.Size)

return (-1);

Data = SList.List[SList.SP];

SList.SP += 1;

return (1);

}

Page 111: Môn: CẤU TRÚC DỮ LIỆU

111

5.2. Ngăn xếp (tt)

5.2.2.d. Hủy ngăn xếp (dùng danh sách đặc)

int CSDelete(CSTACK &SList)

{

delete SList.SList;

return;

}

Page 112: Môn: CẤU TRÚC DỮ LIỆU

112

5.2. Ngăn xếp (tt)

5.2.2. Các thao tác trên ngăn xếp tổ chức bằng danh sách liên kết

5.2.3.a. Khởi tạo ngăn xếp (Initialize)

5.2.3.b. Thêm 1 phần tử vào ngăn xếp (Push)

5.2.3.c. Lấy nội dung 1 phần tử trong ngăn xếp ra xử lý (Pop)

5.2.3.d. Hủy ngăn xếp

Page 113: Môn: CẤU TRÚC DỮ LIỆU

113

5.2. Ngăn xếp (tt)

5.2.3.a. Khởi tạo ngăn xếp (dùng danh sách liên kết)

SSTACK SSInitialize (SSTACK &SList)

{ SList = NULL;

return (SList);

}

Page 114: Môn: CẤU TRÚC DỮ LIỆU

114

5.2. Ngăn xếp (tt)

5.2.3.b. Thêm 1 phần tử vào ngăn xếp (dùng danh sách liên kết)

B1: NewElement = SLLCreateNode(NewData)

B2: if (NewElement == NULL)

Thực hiện BKT

B3: if (SSP == NULL)

B3.1: SSP = NewElement

B3.2: Thực hiện BKT

B4: NewElement ->Next = SSP

B5: SSP = NewElement

BKT: Kết thúc

Page 115: Môn: CẤU TRÚC DỮ LIỆU

115

5.2. Ngăn xếp (tt)

5.2.3.b. Thêm 1 phần tử vào ngăn xếp (dùng danh sách liên kết)

SSTACK SSPush (SSTACK &SList, T NewData)

{ SSTACK NewElement = SLLCreateNode(NewData);

if (NewElement == NULL)

return (NULL);

NewElement ->Next = SList;

SList = NewElement;

return (NewElement);

}

Page 116: Môn: CẤU TRÚC DỮ LIỆU

116

5.2. Ngăn xếp (tt)

5.2.3.c. Lấy nội dung 1 phần tử trong ngăn xếp ra xử lý (dùng danh sách liên kết)

B1: if (SSP == NULL)

Thực hiện BKT

B2: TempElement = SSP

B3: SSP = SSP ->Next

B4: TempElement ->Next = NULL

B5: Data = TempElement->Key

B6: delete TempElement-

BKT: Kết thúc

Page 117: Môn: CẤU TRÚC DỮ LIỆU

117

5.2. Ngăn xếp (tt)5.2.3.c. Lấy nội dung 1 phần tử trong ngăn xếp ra xử lý (dùng

danh sách liên kết)int SSPop (SSTACK &SList, T &Data){

if (SList == NULL)return (-1);

SSTACK TempElement = SList;SList = SList ->Next;TempElement ->Next = NULL;Data = TempElement->Key;delete TempElement;return (1);

}

Page 118: Môn: CẤU TRÚC DỮ LIỆU

118

5.2. Ngăn xếp (tt)

5.2.3.d. Hủy ngăn xếp (dùng danh sách liên kết)

void SSDelete (SSTACK &SList)

{

while (SList != NULL)

{ SSTACK TempElement = SList;

SList = SList ->Next;

TempElement ->Next = NULL;

delete TempElement;

}

}

Page 119: Môn: CẤU TRÚC DỮ LIỆU

119

5.2. Ngăn xếp (tt)

5.3. Ứng dụng của danh sách hạn chế Hàng đợi dùng trong nhiều trường hợp lưu trữ dữ liệu cần xử

lý tuần tự. Ngăn xếp dùng trong việc xử lý dữ liệu truy hồi, đặc biệt trong

việc xử lý đệ quy của các thuật giải.

Page 120: Môn: CẤU TRÚC DỮ LIỆU

120

BÀI TẬP CHƯƠNG 4 Bài tập chương 4, giáo trình Cấu trúc dữ liệu và giải thuật

(Trang 156 -157)