Bài giảng môn Cấu trúc dữ liệu - Chương 4: Danh sách (List)

NỘI DUNG CHƯƠNG 4

1. Khái niệm danh sách

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

3. 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ế

pdf112 trang | Chia sẻ: phuongt97 | Lượt xem: 510 | Lượt tải: 0download
Bạn đang xem trước 20 trang nội dung tài liệu Bài giảng môn Cấu trúc dữ liệu - Chương 4: Danh sách (List), để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Thực hiện BKT B3: IF (Inode == DLLList.DLLLast) Thực hiện BKT B4: Jnode = DLLList.DLLLast B5: IF (Jnode = Inode) Thực hiện B7 B6: ELSE B6.1: If (Jnode->Key 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 B3 BKT: Kết thúc 150 4.3. Danh sách liên kết đôi 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án void 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 PreNode ->Key) Swap(Jnode->Key,Jnode->PreNode->Key) Jnode = Jnode ->PreNode ; } Inode = Inode ->NextNode ; } return; } 151 4.3. Danh sách liên kết đôi 4.3.2.l. Sao chép 1 danh sách thành 1 danh sách mới Thuật toán B1: DLLInitialize(NewList) B2: CurrNode = DLLList.DLLFirst B3: IF (CurrNode == NULL) Thực hiện BKT B4: DLLAddLast(NewList, CurrNode->Key) B5: CurrNode = CurrNode ->NextNode B6: Lặp lại B3 BKT: Kết thúc 152 4.3. Danh sách liên kết đôi 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án DLLPType 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); } 153 4. Danh sách liên kết 4.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. 154 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ế 155 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) 156 5.1. Hàng đợi 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; 157 5.1. Hàng đợi 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; 158 5.1. Hàng đợi 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 159 5.1. Hàng đợi 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 160 5.1. Hàng đợi 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); } 161 5.1. Hàng đợi 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ị đầy B1: IF(CQList.Front ==1 AND CQList.Rear == CQList.Len) Thực hiện BKT B2: IF(CQList.Rear+1 == CQList.Front) Thực hiện BKT B3: IF(CQList.Front = 0) // nếu hàng đợi rỗng CQList.Front = 1 B4: IF(CQList.Rear = CQList.Len) CQList.Rear = 1 B5: ELSE CQList.Rear ++ B6: CQList.List[CQList.Rear] = NewData BKT: Kết thúc 162 5.1. Hàng đợi 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án int 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 =0 if (QList.Rear == QList.Len) QList.Rear = 0; else QList.Rear += 1; QList.List[QList.Rear] = NewData return (QList.Rear ); } 163 5.1. Hàng đợi 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 BKT B2: Data = CQList.List[CQList.Front] B3: IF(CQList.Rear == CQList.Front) B3.1: CQList.Rear = CQList.Front = 0 B3.2: Thực hiện BKT B4: IF (CQList.Front = CQList.Len) CQList.Front = 1 B5: ELSE CQList.Front++ BKT: Kết thúc 164 5.1. Hàng đợi 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án int 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); } 165 5.1. Hàng đợi 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; } 166 5.1. Hàng đợi 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 167 5.1. Hàng đợi 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); } 168 5.1. Hàng đợi 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à NewData B1: NewElement = SLLCreateNode(NewData) B2: IF (NewElement == NULL) Thực hiện BKT B3: IF (SQList.Front == NULL) // hàng đợi dang rỗng B3.1: SQList.Front = SQList.Rear = NewElement B3.2: Thực hiện BKT B4: SQList.Rear->Next = NewElement B5: SQList.Rear = NewElement BKT: Kết thúc 169 5.1. Hàng đợi 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); } 170 5.1. Hàng đợi 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ày B1: IF (SQList.Front == NULL) // nếu hàng đợi bị rỗng Thực hiện BKT B2: TempElement = SQList.Front; B3: SQList.Front = SQList.Front ->Next B4: TempElement ->Next = NULL B5: Data = TempElement ->Key B6: IF (SQList.Front == NULL) SQList.Rear == NULL B7: delete TempElement BKT: Kết thúc 171 5.1. Hàng đợi 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); } 172 5.1. Hàng đợi 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; } 173 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 174 5.2. Ngăn xếp 5.2.1. Cấu trúc dữ liệu Biểu diễn và tổ chức bằng danh sách đặc typedef 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ết typedef struct SElement { T Key; SElement *Next; } SOneElement; typedef struct SOneElement *SSTACK; SSTACK SSP; 175 5.2. Ngăn xếp 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 176 5.2. Ngăn xếp 5.2.2.a. Khởi tạo ngăn xếp (dùng danh sách đặc) B1: CSList.Size = MaxSize B2: CSList.List = new T[MaxSize] B3: IF (CSList.List == NULL) Thực hiện BKT B4: CSList.SP = CSList.Size +1 BKT: Kết thúc T * 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); } 177 5.2. Ngăn xếp 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 BKT B2: CSList.SP -- B3: CSList.List[CSList.SP] = NewData BKT: Kết thúc int CSPush(CSTACK &SList, T NewData) { if (SList.SP == 0) return (-1); SList.SP -= 1; SList.List[SList.SP] = NewData; return (SList.SP); } 178 5.2. Ngăn xếp 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); } 179 5.2. Ngăn xếp 5.2.2.d. Hủy ngăn xếp (dùng danh sách đặc) int CSDelete(CSTACK &SList) { delete SList.SList; return; } 180 5.2. Ngăn xếp 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 181 5.2. Ngăn xếp 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); } 182 5.2. Ngăn xếp 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 183 5.2. Ngăn xếp 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); } 184 5.2. Ngăn xếp 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 185 5.2. Ngăn xếp 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); } 186 5.2. Ngăn xếp 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; } } 187 5.2. Ngăn xếp 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. 188 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)

Các file đính kèm theo tài liệu này:

  • pdfbai_giang_mon_cau_truc_du_lieu_chuong_4_danh_sach_list.pdf